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 struct lcr_msg *message;
1623 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1625 /* ignore information message without digit information */
1626 if (!param->information.id[0])
1631 /* turn off dtmf detection, in case dtmf is sent with keypad information */
1633 trace_header("DTMF (disabling due to keypad)", DIRECTION_IN);
1638 /* if vbox_play is done, the information are just used as they come */
1640 if (e_action->index == ACTION_VBOX_PLAY) {
1641 /* concat dialing string */
1642 SCAT(e_dialinginfo.id, param->information.id);
1647 /* keypad when disconnect but in connected mode */
1648 if (e_state==EPOINT_STATE_OUT_DISCONNECT && e_connectedmode) {
1649 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received after disconnect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1650 /* processing keypad function */
1651 if (param->information.id[0] == '0') {
1657 /* keypad when connected */
1658 if (e_state == EPOINT_STATE_CONNECT || e_state == EPOINT_STATE_IN_ALERTING) {
1659 if (e_enablekeypad) {
1660 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1661 memcpy(&message->param, param, sizeof(union parameter));
1662 message_put(message);
1666 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1667 /* processing keypad function */
1668 if (param->information.id[0] == '0') {
1671 if (param->information.id[0])
1672 keypad_function(param->information.id[0]);
1674 if (e_ext.number[0])
1675 trace_header("KEYPAD (not enabled by extension's settings)", DIRECTION_IN);
1677 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1682 if (e_state != EPOINT_STATE_IN_OVERLAP) {
1683 if (e_ext.number[0])
1684 trace_header("KEYPAD (ignored, not connected and not dialing)", DIRECTION_IN);
1686 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1690 if (!param->information.id[0])
1692 if (e_dialinginfo.id[0]=='\0' && !e_action) {
1693 set_tone(portlist, "dialing");
1696 if (e_action->index==ACTION_OUTDIAL
1697 || e_action->index==ACTION_EXTERNAL
1698 || e_action->index==ACTION_REMOTE) {
1700 set_tone(portlist, "dialing");
1701 else if (!e_extdialing[0])
1702 set_tone(portlist, "dialing");
1704 /* concat dialing string */
1705 SCAT(e_dialinginfo.id, param->information.id);
1709 /* port MESSAGE_DTMF */
1710 void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
1713 struct lcr_msg *message;
1717 /* only if dtmf detection is enabled */
1719 trace_header("DTMF (disabled)", DIRECTION_IN);
1723 trace_header("DTMF", DIRECTION_IN);
1724 add_trace("digit", NULL, "%c", param->dtmf);
1728 NOTE: vbox is now handled due to overlap state
1729 /* if vbox_play is done, the dtmf digits are just used as they come */
1731 if (e_action->index == ACTION_VBOX_PLAY) {
1732 /* concat dialing string */
1733 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id)) {
1734 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1735 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1738 /* continue to process *X# sequences */
1742 /* check for *X# sequence */
1743 if (e_state == EPOINT_STATE_CONNECT || e_state == EPOINT_STATE_IN_ALERTING) {
1744 if (e_enablekeypad) {
1745 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1746 memcpy(&message->param, param, sizeof(union parameter));
1747 message_put(message);
1750 if (e_dtmf_time+3 < now) {
1751 /* the last digit was too far in the past to be a sequence */
1752 if (param->dtmf == '*')
1753 /* only start is allowed in the sequence */
1758 /* we have a sequence of digits, see what we got */
1759 if (param->dtmf == '*')
1761 else if (param->dtmf>='0' && param->dtmf<='9') {
1762 /* we need to have a star before we receive the digit of the sequence */
1763 if (e_dtmf_last == '*')
1764 e_dtmf_last = param->dtmf;
1765 } else if (param->dtmf == '#') {
1767 if (e_dtmf_last>='0' && e_dtmf_last<='9') {
1768 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf sequence *%c# detected.\n", ea_endpoint->ep_serial, e_dtmf_last);
1769 if (e_dtmf_last == '0') {
1773 /* processing keypad function */
1775 keypad_function(e_dtmf_last);
1781 /* set last time of dtmf */
1786 /* check for ## hookflash during dialing */
1788 if (e_action->index==ACTION_PASSWORD
1789 || e_action->index==ACTION_PASSWORD_WRITE)
1791 if (param->dtmf=='#') { /* current digit is '#' */
1792 if (e_state==EPOINT_STATE_IN_DISCONNECT
1793 || (e_state!=EPOINT_STATE_CONNECT && e_dtmf_time+3>=now && e_dtmf_last=='#')) { /* when disconnected, just #. when dialing, ##. */
1807 /* dialing using dtmf digit */
1808 if (e_state==EPOINT_STATE_IN_OVERLAP){ // && e_state==e_connectedmode)
1809 if (e_dialinginfo.id[0]=='\0' && !e_action) {
1810 set_tone(portlist, "dialing");
1812 /* concat dialing string */
1813 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id)) {
1814 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1815 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1821 /* port MESSAGE_CRYPT */
1822 void EndpointAppPBX::port_crypt(struct port_list *portlist, int message_type, union parameter *param)
1824 /* send crypt response to cryptman */
1825 if (param->crypt.type == CR_MESSAGE_IND)
1826 cryptman_msg2man(param->crypt.data, param->crypt.len);
1828 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
1831 /* port MESSAGE_OVERLAP */
1832 void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, union parameter *param)
1834 struct lcr_msg *message;
1836 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1838 /* signal to call tool */
1839 admin_call_response(e_adminid, ADMIN_CALL_SETUP_ACK, "", 0, 0, 0);
1841 if (e_dialing_queue[0] && portlist) {
1842 /* send what we have not dialed yet, because we had no setup complete */
1843 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing pending digits: '%s'\n", ea_endpoint->ep_serial, e_dialing_queue);
1844 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
1845 SCPY(message->param.information.id, e_dialing_queue);
1846 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
1847 message_put(message);
1848 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
1849 e_dialing_queue[0] = '\0';
1851 /* check if pattern is available */
1852 if (!ea_endpoint->ep_portlist->next && portlist->early_b) { /* one port_list relation and tones available */
1853 /* indicate patterns */
1854 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1855 message_put(message);
1857 /* connect audio, if not already */
1858 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1859 message->param.audiopath = 1;
1860 message_put(message);
1862 /* indicate no patterns */
1863 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1864 message_put(message);
1866 /* disconnect audio, if not already */
1867 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1868 message->param.audiopath = 0;
1869 message_put(message);
1871 new_state(EPOINT_STATE_OUT_OVERLAP);
1872 /* if we are in a join */
1873 if (ea_endpoint->ep_join_id) {
1874 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1875 memcpy(&message->param, param, sizeof(union parameter));
1876 message_put(message);
1880 /* port MESSAGE_PROCEEDING */
1881 void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_type, union parameter *param)
1883 struct lcr_msg *message;
1885 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1887 /* signal to call tool */
1888 admin_call_response(e_adminid, ADMIN_CALL_PROCEEDING, "", 0, 0, 0);
1890 e_state = EPOINT_STATE_OUT_PROCEEDING;
1891 /* check if pattern is availatle */
1892 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) { /* one port_list relation and tones available */
1893 /* indicate patterns */
1894 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1895 message_put(message);
1897 /* connect audio, if not already */
1898 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1899 message->param.audiopath = 1;
1900 message_put(message);
1902 /* indicate no patterns */
1903 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1904 message_put(message);
1906 /* disconnect audio, if not already */
1907 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1908 message->param.audiopath = 0;
1909 message_put(message);
1911 /* if we are in a call */
1912 if (ea_endpoint->ep_join_id) {
1913 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1914 memcpy(&message->param, param, sizeof(union parameter));
1915 message_put(message);
1919 /* port MESSAGE_ALERTING */
1920 void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type, union parameter *param)
1922 struct lcr_msg *message;
1924 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1926 /* signal to call tool */
1927 admin_call_response(e_adminid, ADMIN_CALL_ALERTING, "", 0, 0, 0);
1930 // set_tone(portlist, "hold");
1932 new_state(EPOINT_STATE_OUT_ALERTING);
1933 /* check if pattern is available */
1934 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) { /* one port_list relation and tones available */
1935 /* indicate patterns */
1936 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1937 message_put(message);
1939 /* connect audio, if not already */
1940 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1941 message->param.audiopath = 1;
1942 message_put(message);
1944 /* indicate no patterns */
1945 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1946 message_put(message);
1948 /* disconnect audio, if not already */
1949 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1950 message->param.audiopath = 0;
1951 message_put(message);
1953 /* if we are in a call */
1954 if (ea_endpoint->ep_join_id) {
1955 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1956 memcpy(&message->param, param, sizeof(union parameter));
1957 message_put(message);
1961 /* port MESSAGE_CONNECT */
1962 void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, union parameter *param)
1964 struct lcr_msg *message;
1966 unsigned int port_id = portlist->port_id;
1967 struct port_list *tportlist;
1969 struct interface *interface;
1972 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1974 /* signal to call tool */
1975 admin_call_response(e_adminid, ADMIN_CALL_CONNECT, numberrize_callerinfo(param->connectinfo.id,param->connectinfo.ntype, options.national, options.international), 0, 0, 0);
1977 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_connectinfo));
1978 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (start)\n", ea_endpoint->ep_serial);
1979 while(ea_endpoint->ep_portlist->next) { /* as long as we have at least two ports */
1980 tportlist = ea_endpoint->ep_portlist;
1981 if (tportlist->port_id == port_id) /* if the first portlist is the calling one, the second must be a different one */
1982 tportlist = tportlist->next;
1983 if (tportlist->port_id == port_id)
1984 FATAL("EPOINT(%d) this should not happen since the portlist list must not have two links to the same port - exitting.\n");
1985 message = message_create(ea_endpoint->ep_serial, tportlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1986 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
1987 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1988 message_put(message);
1989 logmessage(message->type, &message->param, tportlist->port_id, DIRECTION_OUT);
1990 ea_endpoint->free_portlist(tportlist);
1992 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (end)\n", ea_endpoint->ep_serial);
1997 /* screen incoming connected id */
1998 interface = interface_first;
2000 if (!strcmp(e_connectinfo.interface, interface->name)) {
2003 interface = interface->next;
2006 do_screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface);
2008 /* screen connected name */
2010 SCPY(e_connectinfo.name, e_ext.name);
2012 /* add internal id to colp */
2013 SCPY(e_connectinfo.extension, e_ext.number);
2015 /* we store the connected port number */
2016 SCPY(e_extension_interface, e_connectinfo.interface);
2018 /* for internal and am calls, we get the extension's id */
2019 if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE) {
2020 SCPY(e_connectinfo.id, e_ext.callerid);
2021 SCPY(e_connectinfo.extension, e_ext.number);
2022 e_connectinfo.itype = INFO_ITYPE_ISDN_EXTENSION;
2023 e_connectinfo.ntype = e_ext.callerid_type;
2024 e_connectinfo.present = e_ext.callerid_present;
2026 if (portlist->port_type==PORT_TYPE_VBOX_OUT) {
2027 e_connectinfo.itype = INFO_ITYPE_VBOX;
2028 e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2031 new_state(EPOINT_STATE_CONNECT);
2033 /* set volume of rx and tx */
2034 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0) {
2035 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2036 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2037 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
2038 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
2039 message_put(message);
2042 unsched_timer(&e_cfnr_timeout);
2043 unsched_timer(&e_cfnr_call_timeout);
2044 if (e_ext.number[0])
2045 e_dtmf = 1; /* allow dtmf */
2048 /* other calls with no caller id (or not available for the extension) and force colp */
2049 if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE) {
2050 e_connectinfo.ntype = INFO_NTYPE_NOTPRESENT;
2051 if (portlist->port_type==PORT_TYPE_DSS1_TE_OUT
2052 || portlist->port_type==PORT_TYPE_DSS1_NT_OUT
2053 || portlist->port_type==PORT_TYPE_GSM_BS_OUT
2054 || portlist->port_type==PORT_TYPE_GSM_MS_OUT) { /* external extension answered */
2055 port = find_port_id(portlist->port_id);
2057 SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.id, &e_connectinfo.ntype, options.national, options.international));
2058 e_connectinfo.present = INFO_PRESENT_ALLOWED;
2063 /* send connect to join */
2064 if (ea_endpoint->ep_join_id) {
2065 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2066 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
2067 message_put(message);
2069 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2070 message->param.audiopath = 1;
2071 message_put(message);
2072 } else if (!e_adminid) {
2074 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have a callback, so we create a call with cbcaller: \"%s\".\n", ea_endpoint->ep_serial, e_cbcaller);
2075 SCPY(e_ext.number, e_cbcaller);
2076 new_state(EPOINT_STATE_IN_OVERLAP);
2077 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) callback from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2079 /* get extension's info about terminal */
2080 if (!read_extension(&e_ext, e_ext.number)) {
2081 /* extension doesn't exist */
2082 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2083 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
2084 new_state(EPOINT_STATE_OUT_DISCONNECT);
2085 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
2089 /* put prefix in front of e_cbdialing */
2090 SPRINT(buffer, "%s%s", e_ext.prefix, e_cbdialing);
2091 SCPY(e_dialinginfo.id, buffer);
2092 e_dialinginfo.itype = INFO_ITYPE_ISDN;
2093 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
2095 /* use caller id (or if exist: id_next_call) for this call */
2096 e_callerinfo.screen = INFO_SCREEN_NETWORK;
2097 SCPY(e_callerinfo.extension, e_ext.number);
2098 if (e_ext.id_next_call_present >= 0) {
2099 SCPY(e_callerinfo.id, e_ext.id_next_call);
2100 e_callerinfo.present = e_ext.id_next_call_present;
2101 e_callerinfo.ntype = e_ext.id_next_call_type;
2102 e_ext.id_next_call_present = -1;
2103 /* extension is written */
2104 write_extension(&e_ext, e_ext.number);
2106 SCPY(e_callerinfo.id, e_ext.callerid);
2107 e_callerinfo.present = e_ext.callerid_present;
2108 e_callerinfo.ntype = e_ext.callerid_type;
2110 e_callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
2112 e_connectedmode = 1; /* dtmf-hangup & disconnect prevention */
2115 /* check if caller id is NOT authenticated */
2116 if (!parse_callbackauth(e_ext.number, &e_callbackinfo)) {
2117 /* make call state to enter password */
2118 new_state(EPOINT_STATE_IN_OVERLAP);
2119 e_action = &action_password_write;
2120 unsched_timer(&e_match_timeout);
2121 e_match_to_action = NULL;
2122 e_dialinginfo.id[0] = '\0';
2123 e_extdialing = strchr(e_dialinginfo.id, '\0');
2124 schedule_timer(&e_password_timeout, 20, 0);
2127 /* incoming call (callback) */
2128 e_ruleset = ruleset_main;
2130 e_rule = e_ruleset->rule_first;
2132 e_extdialing = e_dialinginfo.id;
2133 if (e_dialinginfo.id[0]) {
2134 set_tone(portlist, "dialing");
2137 set_tone(portlist, "dialpbx");
2140 } else { /* testcall */
2141 set_tone(portlist, "hold");
2144 /* start recording if enabled, not when answering machine answers */
2145 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)) {
2146 /* check if we are a terminal */
2147 if (e_ext.number[0] == '\0')
2148 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
2150 port = find_port_id(portlist->port_id);
2152 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
2157 /* port MESSAGE_DISCONNECT MESSAGE_RELEASE */
2158 void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
2160 struct lcr_msg *message;
2162 unsigned int port_id = portlist->port_id;
2166 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2168 /* signal to call tool */
2169 admin_call_response(e_adminid, (message_type==MESSAGE_DISCONNECT)?ADMIN_CALL_DISCONNECT:ADMIN_CALL_RELEASE, "", param->disconnectinfo.cause, param->disconnectinfo.location, 0);
2171 //#warning does this work? only disconnect when incoming port hat not already disconnected yet?
2172 if (e_state==EPOINT_STATE_IN_DISCONNECT && message_type!=MESSAGE_RELEASE){ // || e_state==EPOINT_STATE_OUT_DISCONNECT || e_state==EPOINT_STATE_IDLE)
2173 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are already disconnected.\n", ea_endpoint->ep_serial);
2178 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);
2179 collect_cause(&e_multipoint_cause, &e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location);
2180 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new multipoint cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location);
2182 /* check if we have more than one portlist relation and we just ignore the disconnect */
2183 if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist->next) {
2184 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the disconnect was from a multipoint call. we just release that relation.\n", ea_endpoint->ep_serial);
2185 portlist = ea_endpoint->ep_portlist;
2187 if (portlist->port_id == port_id)
2189 portlist = portlist->next;
2192 FATAL("EPOINT(%d) no portlist related to the calling port.\n", ea_endpoint->ep_serial);
2193 if (message_type != MESSAGE_RELEASE) {
2194 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2195 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2196 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2197 message_put(message);
2198 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2200 ea_endpoint->free_portlist(portlist);
2201 return; /* one relation removed */
2203 if (e_state == EPOINT_STATE_CONNECT) {
2204 /* use cause from port after connect */
2205 cause = param->disconnectinfo.cause;
2206 location = param->disconnectinfo.location;
2208 /* use multipoint cause if no connect yet */
2209 if (e_multipoint_cause) {
2210 cause = e_multipoint_cause;
2211 location = e_multipoint_location;
2213 cause = CAUSE_NOUSER;
2214 location = LOCATION_PRIVATE_LOCAL;
2218 unsched_timer(&e_cfnr_timeout);
2219 unsched_timer(&e_cfnr_call_timeout);
2221 /* process hangup */
2222 process_hangup(e_join_cause, e_join_location);
2223 e_multipoint_cause = 0;
2224 e_multipoint_location = 0;
2226 if (message_type == MESSAGE_DISCONNECT) {
2227 /* tone to disconnected end */
2228 SPRINT(buffer, "cause_%02x", cause);
2229 if (ea_endpoint->ep_portlist)
2230 set_tone(ea_endpoint->ep_portlist, buffer);
2232 new_state(EPOINT_STATE_IN_DISCONNECT);
2235 if (ea_endpoint->ep_join_id) {
2236 int haspatterns = 0;
2237 /* check if pattern is available */
2238 if (ea_endpoint->ep_portlist)
2239 if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->early_b)
2240 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
2241 && message_type != MESSAGE_RELEASE) // if we release, we are done
2244 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has patterns.\n", ea_endpoint->ep_serial);
2245 /* indicate patterns */
2246 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2247 message_put(message);
2248 /* connect audio, if not already */
2249 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2250 message->param.audiopath = 1;
2251 message_put(message);
2252 /* send disconnect */
2253 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2254 memcpy(&message->param, param, sizeof(union parameter));
2255 message_put(message);
2256 /* disable encryption if disconnected */
2257 //PERROR("REMOVE ME: state =%d, %d\n", e_crypt_state, e_crypt);
2259 cryptman_message(CI_DISCONNECT_IND, NULL, 0);
2262 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
2265 if (message_type == MESSAGE_RELEASE)
2266 ea_endpoint->free_portlist(portlist);
2267 release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, callcause, portcause */
2268 return; /* must exit here */
2271 /* port MESSAGE_TIMEOUT */
2272 void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type, union parameter *param)
2276 trace_header("TIMEOUT", DIRECTION_IN);
2277 message_type = MESSAGE_DISCONNECT;
2278 switch (param->state) {
2279 case PORT_STATE_OUT_SETUP:
2280 case PORT_STATE_OUT_OVERLAP:
2281 add_trace("state", NULL, "outgoing setup/dialing");
2283 /* no user responding */
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_SETUP:
2288 case PORT_STATE_IN_OVERLAP:
2289 add_trace("state", NULL, "incoming setup/dialing");
2290 param->disconnectinfo.cause = CAUSE_INVALID; /* number incomplete */
2291 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2294 case PORT_STATE_OUT_PROCEEDING:
2295 add_trace("state", NULL, "outgoing proceeding");
2297 param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
2298 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2299 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2300 return; /* must exit here */
2302 case PORT_STATE_IN_PROCEEDING:
2303 add_trace("state", NULL, "incoming proceeding");
2304 param->disconnectinfo.cause = CAUSE_NOUSER;
2305 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL; /* no user responding */
2308 case PORT_STATE_OUT_ALERTING:
2309 add_trace("state", NULL, "outgoing alerting");
2311 param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
2312 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2313 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2314 return; /* must exit here */
2316 case PORT_STATE_CONNECT:
2317 add_trace("state", NULL, "connect");
2319 param->disconnectinfo.cause = CAUSE_NORMAL; /* normal */
2320 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2321 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2322 return; /* must exit here */
2324 case PORT_STATE_IN_ALERTING:
2325 add_trace("state", NULL, "incoming alerting");
2326 param->disconnectinfo.cause = CAUSE_NOANSWER;
2327 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2330 case PORT_STATE_IN_DISCONNECT:
2331 case PORT_STATE_OUT_DISCONNECT:
2332 add_trace("state", NULL, "disconnect");
2334 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
2335 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2336 return; /* must exit here */
2339 param->disconnectinfo.cause = 31; /* normal unspecified */
2340 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2343 /* release call, disconnect isdn */
2345 new_state(EPOINT_STATE_OUT_DISCONNECT);
2346 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2347 SCPY(e_tone, cause);
2349 set_tone(portlist, cause);
2350 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2351 portlist = portlist->next;
2353 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
2356 /* port MESSAGE_NOTIFY */
2357 void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, union parameter *param)
2359 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2361 struct lcr_msg *message;
2362 const char *logtext = "";
2365 /* signal to call tool */
2366 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);
2367 if (param->notifyinfo.notify) {
2368 e_rx_state = track_notify(e_rx_state, param->notifyinfo.notify);
2371 /* if we get notification from stack, local shows if we disabled/enabled audio stream */
2372 if (param->notifyinfo.local) switch(param->notifyinfo.notify) {
2373 case INFO_NOTIFY_REMOTE_HOLD:
2374 case INFO_NOTIFY_USER_SUSPENDED:
2375 /* tell call about it */
2376 if (ea_endpoint->ep_join_id) {
2377 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2378 message->param.audiopath = 0;
2379 message_put(message);
2383 case INFO_NOTIFY_REMOTE_RETRIEVAL:
2384 case INFO_NOTIFY_USER_RESUMED:
2385 /* set volume of rx and tx */
2386 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
2387 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
2389 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2390 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2391 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
2392 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
2393 message_put(message);
2395 /* set current tone */
2397 set_tone(portlist, e_tone);
2398 /* tell call about it */
2399 if (ea_endpoint->ep_join_id) {
2400 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2401 message->param.audiopath = 1;
2402 message_put(message);
2407 /* get name of notify */
2408 switch(param->notifyinfo.notify) {
2413 logtext = "USER_SUSPENDED";
2416 logtext = "BEARER_SERVICE_CHANGED";
2419 logtext = "USER_RESUMED";
2422 logtext = "CONFERENCE_ESTABLISHED";
2425 logtext = "CONFERENCE_DISCONNECTED";
2428 logtext = "OTHER_PARTY_ADDED";
2431 logtext = "ISOLATED";
2434 logtext = "REATTACHED";
2437 logtext = "OTHER_PARTY_ISOLATED";
2440 logtext = "OTHER_PARTY_REATTACHED";
2443 logtext = "OTHER_PARTY_SPLIT";
2446 logtext = "OTHER_PARTY_DISCONNECTED";
2449 logtext = "CONFERENCE_FLOATING";
2452 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
2455 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
2458 logtext = "CALL_IS_A_WAITING_CALL";
2461 logtext = "DIVERSION_ACTIVATED";
2464 logtext = "RESERVED_CT_1";
2467 logtext = "RESERVED_CT_2";
2470 logtext = "REVERSE_CHARGING";
2473 logtext = "REMOTE_HOLD";
2476 logtext = "REMOTE_RETRIEVAL";
2479 logtext = "CALL_IS_DIVERTING";
2482 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
2487 /* notify call if available */
2488 if (ea_endpoint->ep_join_id) {
2489 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOTIFY);
2490 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
2491 message_put(message);
2496 /* port MESSAGE_PROGRESS */
2497 void EndpointAppPBX::port_progress(struct port_list *portlist, int message_type, union parameter *param)
2499 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2501 struct lcr_msg *message;
2503 /* signal to call tool */
2504 admin_call_response(e_adminid, ADMIN_CALL_PROGRESS, "", 0, param->progressinfo.location, param->progressinfo.progress);
2506 /* send progress to call if available */
2507 if (ea_endpoint->ep_join_id) {
2508 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PROGRESS);
2509 memcpy(&message->param.progressinfo, ¶m->progressinfo, sizeof(struct progress_info));
2510 message_put(message);
2515 /* port MESSAGE_FACILITY */
2516 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
2518 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2520 struct lcr_msg *message;
2522 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_FACILITY);
2523 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2524 message_put(message);
2527 /* port MESSAGE_SUSPEND */
2528 /* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
2529 void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
2531 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2533 /* epoint is now parked */
2534 ea_endpoint->ep_park = 1;
2535 memcpy(ea_endpoint->ep_park_callid, param->parkinfo.callid, sizeof(ea_endpoint->ep_park_callid));
2536 ea_endpoint->ep_park_len = (param->parkinfo.len>8)?8:param->parkinfo.len;
2538 /* remove port relation */
2539 ea_endpoint->free_portlist(portlist);
2542 /* port MESSAGE_RESUME */
2543 /* NOTE: before resume, the active-notification must be done in order to set call mixer */
2544 void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
2546 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2548 /* epoint is now resumed */
2549 ea_endpoint->ep_park = 0;
2553 /* port MESSAGE_ENABLEKEYPAD */
2554 void EndpointAppPBX::port_enablekeypad(struct port_list *portlist, int message_type, union parameter *param)
2556 struct lcr_msg *message;
2558 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2560 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_ENABLEKEYPAD);
2561 memcpy(&message->param, param, sizeof(union parameter));
2562 message_put(message);
2566 /* port sends message to the endpoint
2568 void EndpointAppPBX::ea_message_port(unsigned int port_id, int message_type, union parameter *param)
2570 struct port_list *portlist;
2572 portlist = ea_endpoint->ep_portlist;
2574 if (port_id == portlist->port_id)
2576 portlist = portlist->next;
2579 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);
2583 // PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
2584 switch(message_type) {
2585 case MESSAGE_DATA: /* data from port */
2586 /* check if there is a call */
2587 if (!ea_endpoint->ep_join_id)
2589 /* continue if only one portlist */
2590 if (ea_endpoint->ep_portlist->next != NULL)
2592 /* forward message */
2593 message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2596 case MESSAGE_TONE_EOF: /* tone is end of file */
2597 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
2599 if (e_action->index == ACTION_VBOX_PLAY) {
2602 if (e_action->index == ACTION_EFI) {
2608 case MESSAGE_TONE_COUNTER: /* counter info received */
2609 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);
2611 if (e_action->index == ACTION_VBOX_PLAY) {
2612 e_vbox_counter = param->counter.current;
2613 if (param->counter.max >= 0)
2614 e_vbox_counter_max = param->counter.max;
2618 /* PORT sends SETUP message */
2620 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);
2621 if (e_state!=EPOINT_STATE_IDLE) {
2622 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
2625 port_setup(portlist, message_type, param);
2628 /* PORT sends INFORMATION message */
2629 case MESSAGE_INFORMATION: /* additional digits received */
2630 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);
2631 port_information(portlist, message_type, param);
2634 /* PORT sends FACILITY message */
2635 case MESSAGE_FACILITY:
2636 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2637 port_facility(portlist, message_type, param);
2640 /* PORT sends DTMF message */
2641 case MESSAGE_DTMF: /* dtmf digits received */
2642 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);
2643 port_dtmf(portlist, message_type, param);
2646 /* PORT sends CRYPT message */
2647 case MESSAGE_CRYPT: /* crypt response received */
2648 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) crypt response=%d\n", ea_endpoint->ep_serial, param->crypt.type);
2649 port_crypt(portlist, message_type, param);
2652 /* PORT sends MORE message */
2653 case MESSAGE_OVERLAP:
2654 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);
2655 if (e_state != EPOINT_STATE_OUT_SETUP) {
2656 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);
2659 port_overlap(portlist, message_type, param);
2662 /* PORT sends PROCEEDING message */
2663 case MESSAGE_PROCEEDING: /* port is proceeding */
2664 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);
2665 if (e_state!=EPOINT_STATE_OUT_SETUP
2666 && e_state!=EPOINT_STATE_OUT_OVERLAP) {
2667 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);
2670 port_proceeding(portlist, message_type, param);
2673 /* PORT sends ALERTING message */
2674 case MESSAGE_ALERTING:
2675 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);
2676 if (e_state!=EPOINT_STATE_OUT_SETUP
2677 && e_state!=EPOINT_STATE_OUT_OVERLAP
2678 && e_state!=EPOINT_STATE_OUT_PROCEEDING) {
2679 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);
2682 port_alerting(portlist, message_type, param);
2685 /* PORT sends CONNECT message */
2686 case MESSAGE_CONNECT:
2687 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);
2688 if (e_state!=EPOINT_STATE_OUT_SETUP
2689 && e_state!=EPOINT_STATE_OUT_OVERLAP
2690 && e_state!=EPOINT_STATE_OUT_PROCEEDING
2691 && e_state!=EPOINT_STATE_OUT_ALERTING) {
2692 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
2695 port_connect(portlist, message_type, param);
2698 /* PORT sends DISCONNECT message */
2699 case MESSAGE_DISCONNECT: /* port is disconnected */
2700 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);
2701 port_disconnect_release(portlist, message_type, param);
2704 /* PORT sends a RELEASE message */
2705 case MESSAGE_RELEASE: /* port releases */
2706 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);
2707 /* portlist is release at port_disconnect_release, thanx Paul */
2708 port_disconnect_release(portlist, message_type, param);
2711 /* PORT sends a TIMEOUT message */
2712 case MESSAGE_TIMEOUT:
2713 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);
2714 port_timeout(portlist, message_type, param);
2715 break; /* release */
2717 /* PORT sends a NOTIFY message */
2718 case MESSAGE_NOTIFY:
2719 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);
2720 port_notify(portlist, message_type, param);
2723 /* PORT sends a PROGRESS message */
2724 case MESSAGE_PROGRESS:
2725 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);
2726 port_progress(portlist, message_type, param);
2729 /* PORT sends a SUSPEND message */
2730 case MESSAGE_SUSPEND:
2731 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);
2732 port_suspend(portlist, message_type, param);
2733 break; /* suspend */
2735 /* PORT sends a RESUME message */
2736 case MESSAGE_RESUME:
2737 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);
2738 port_resume(portlist, message_type, param);
2742 kann nach dem test gelöscht werden, da eine direkte funktion im join und im mISDN zum austausch der message existiert
2743 /* port assigns bchannel */
2744 case MESSAGE_BCHANNEL: /* bchannel assignment messafe */
2745 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);
2746 /* only one port is expected to be connected to bchannel */
2747 message = message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2748 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_IN);
2752 /* PORT requests DTMF */
2753 case MESSAGE_ENABLEKEYPAD:
2754 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') requests DTMF/KEYPAD.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2755 port_enablekeypad(portlist, message_type, param);
2760 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);
2763 /* Note: this endpoint may be destroyed, so we MUST return */
2767 /* messages from join
2769 /* join MESSAGE_CRYPT */
2770 void EndpointAppPBX::join_crypt(struct port_list *portlist, int message_type, union parameter *param)
2772 switch(param->crypt.type) {
2773 /* message from remote port to "crypt manager" */
2774 case CU_ACTK_REQ: /* activate key-exchange */
2775 case CU_ACTS_REQ: /* activate shared key */
2776 case CU_DACT_REQ: /* deactivate */
2777 case CU_INFO_REQ: /* request last info message */
2778 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2781 /* message from "crypt manager" to user */
2782 case CU_ACTK_CONF: /* key-echange done */
2783 case CU_ACTS_CONF: /* shared key done */
2784 case CU_DACT_CONF: /* deactivated */
2785 case CU_DACT_IND: /* deactivated */
2786 case CU_ERROR_IND: /* receive error message */
2787 case CU_INFO_IND: /* receive info message */
2788 case CU_INFO_CONF: /* receive info message */
2789 encrypt_result(param->crypt.type, (char *)param->crypt.data);
2793 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);
2797 /* join MESSAGE_INFORMATION */
2798 void EndpointAppPBX::join_information(struct port_list *portlist, int message_type, union parameter *param)
2800 struct lcr_msg *message;
2805 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2806 memcpy(&message->param.information, ¶m->information, sizeof(struct dialing_info));
2807 message_put(message);
2808 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2809 portlist = portlist->next;
2813 /* join MESSAGE_FACILITY */
2814 void EndpointAppPBX::join_facility(struct port_list *portlist, int message_type, union parameter *param)
2816 struct lcr_msg *message;
2818 if (!e_ext.facility && e_ext.number[0]) {
2823 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_FACILITY);
2824 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2825 message_put(message);
2826 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2827 portlist = portlist->next;
2831 /* join MESSAGE_MORE */
2832 void EndpointAppPBX::join_overlap(struct port_list *portlist, int message_type, union parameter *param)
2834 struct lcr_msg *message;
2836 new_state(EPOINT_STATE_IN_OVERLAP);
2839 if (e_join_pattern && e_ext.own_setup) {
2840 /* disconnect audio */
2841 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2842 message->param.audiopath = 0;
2843 message_put(message);
2845 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL) {
2846 if (e_dialinginfo.id[0])
2847 set_tone(portlist, "dialing");
2849 set_tone(portlist, "dialtone");
2852 if (e_dialinginfo.id[0]) {
2853 set_tone(portlist, "dialing");
2855 if (e_ext.number[0])
2856 set_tone(portlist, "dialpbx");
2858 set_tone(portlist, "dialtone");
2862 /* join MESSAGE_PROCEEDING */
2863 void EndpointAppPBX::join_proceeding(struct port_list *portlist, int message_type, union parameter *param)
2865 struct lcr_msg *message;
2867 new_state(EPOINT_STATE_IN_PROCEEDING);
2869 /* own proceeding tone */
2870 if (e_join_pattern) {
2871 /* connect / disconnect audio */
2872 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2873 if (e_ext.own_proceeding)
2874 message->param.audiopath = 0;
2876 message->param.audiopath = 1;
2877 message_put(message);
2879 // UCPY(e_join_tone, "proceeding");
2881 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
2882 message_put(message);
2883 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2885 set_tone(portlist, "proceeding");
2888 /* join MESSAGE_ALERTING */
2889 void EndpointAppPBX::join_alerting(struct port_list *portlist, int message_type, union parameter *param)
2891 struct lcr_msg *message;
2893 new_state(EPOINT_STATE_IN_ALERTING);
2895 /* own alerting tone */
2896 if (e_join_pattern) {
2897 /* connect / disconnect audio */
2898 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2899 if (e_ext.own_alerting)
2900 message->param.audiopath = 0;
2902 message->param.audiopath = 1;
2903 message_put(message);
2906 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
2907 message_put(message);
2908 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2910 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL) {
2911 set_tone(portlist, "ringing");
2914 if (e_ext.number[0])
2915 set_tone(portlist, "ringpbx");
2917 set_tone(portlist, "ringing");
2919 if (e_ext.number[0])
2920 e_dtmf = 1; /* allow dtmf */
2923 /* join MESSAGE_CONNECT */
2924 void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type, union parameter *param)
2926 struct lcr_msg *message;
2929 new_state(EPOINT_STATE_CONNECT);
2930 // UCPY(e_join_tone, "");
2932 if (e_ext.number[0])
2933 e_dtmf = 1; /* allow dtmf */
2936 unsched_timer(&e_powerdial_timeout);
2937 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_callerinfo));
2939 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
2940 memcpy(&message->param, param, sizeof(union parameter));
2942 /* screen clip if prefix is required */
2943 if (e_ext.number[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0]) {
2944 SCPY(message->param.connectinfo.id, e_ext.clip_prefix);
2945 SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype, options.national, options.international));
2946 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2949 /* use internal caller id */
2950 if (e_ext.number[0] && e_connectinfo.extension[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore)) {
2951 SCPY(message->param.connectinfo.id, e_connectinfo.extension);
2952 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2955 /* handle restricted caller ids */
2956 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);
2957 /* display callerid if desired for extension */
2958 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));
2960 /* use conp, if enabld */
2961 // if (!e_ext.centrex)
2962 // message->param.connectinfo.name[0] = '\0';
2965 message_put(message);
2966 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2968 set_tone(portlist, NULL);
2970 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2971 message->param.audiopath = 1;
2972 message_put(message);
2977 /* join MESSAGE_DISCONNECT MESSAGE_RELEASE */
2978 void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *param)
2981 struct lcr_msg *message;
2982 struct port_list *portlist = NULL;
2986 /* be sure that we are active */
2988 e_tx_state = NOTIFY_STATE_ACTIVE;
2990 /* we are powerdialing, if e_powerdial_on is set and limit is not exceeded if given */
2991 if (e_powerdial_on && ((e_powercount+1)<e_powerlimit || e_powerlimit<1)) {
2992 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL,0 ); /* RELEASE_TYPE, join, port */
2994 /* set time for power dialing */
2995 schedule_timer(&e_powerdial_timeout, (int)e_powerdelay, 0); /* set redial in the future */
2998 /* set redial tone */
2999 if (ea_endpoint->ep_portlist) {
3002 set_tone(ea_endpoint->ep_portlist, "redial");
3003 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);
3004 /* send proceeding when powerdialing and still setup (avoid dialing timeout) */
3005 if (e_state==EPOINT_STATE_IN_OVERLAP) {
3006 new_state(EPOINT_STATE_IN_PROCEEDING);
3007 if (ea_endpoint->ep_portlist) {
3008 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3009 message_put(message);
3010 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3012 /* caused the error, that the first knock sound was not there */
3013 /* set_tone(portlist, "proceeding"); */
3015 /* send display of powerdialing */
3016 if (e_ext.display_dialing) {
3017 portlist = ea_endpoint->ep_portlist;
3019 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3021 SPRINT(message->param.notifyinfo.display, "Retry %d of %d", e_powercount, e_powerlimit);
3023 SPRINT(message->param.notifyinfo.display, "Retry %d", e_powercount);
3024 message_put(message);
3025 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3026 portlist = portlist->next;
3036 if ((e_state!=EPOINT_STATE_CONNECT
3037 && e_state!=EPOINT_STATE_OUT_DISCONNECT
3038 && e_state!=EPOINT_STATE_IN_OVERLAP
3039 && e_state!=EPOINT_STATE_IN_PROCEEDING
3040 && e_state!=EPOINT_STATE_IN_ALERTING)
3041 || !ea_endpoint->ep_portlist) { /* or no port */
3042 process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
3043 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause, 0); /* RELEASE_TYPE, join, port */
3044 return; /* must exit here */
3047 if (!e_join_cause) {
3048 e_join_cause = param->disconnectinfo.cause;
3049 e_join_location = param->disconnectinfo.location;
3052 /* on release we need the audio again! */
3053 if (message_type == MESSAGE_RELEASE) {
3055 ea_endpoint->ep_join_id = 0;
3057 /* disconnect and select tone */
3058 new_state(EPOINT_STATE_OUT_DISCONNECT);
3059 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
3060 /* if own_cause, we must release the join */
3061 if (e_ext.own_cause /* own cause */
3062 || !e_join_pattern) { /* no patterns */
3063 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);
3064 if (message_type != MESSAGE_RELEASE)
3065 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
3067 } else { /* else we enable audio */
3068 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3069 message->param.audiopath = 1;
3070 message_put(message);
3072 /* send disconnect message */
3073 SCPY(e_tone, cause);
3074 portlist = ea_endpoint->ep_portlist;
3076 set_tone(portlist, cause);
3077 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
3078 portlist = portlist->next;
3082 /* join MESSAGE_SETUP */
3083 void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, union parameter *param)
3085 struct lcr_msg *message;
3086 // struct interface *interface;
3088 /* if we already in setup state, we just update the dialing with new digits */
3089 if (e_state == EPOINT_STATE_OUT_SETUP
3090 || e_state == EPOINT_STATE_OUT_OVERLAP) {
3091 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we are in setup state, so we do overlap dialing.\n", ea_endpoint->ep_serial);
3092 /* if digits changed, what we have already dialed */
3093 if (!!strncmp(e_dialinginfo.id,param->setup.dialinginfo.id,strlen(e_dialinginfo.id))) {
3094 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);
3095 /* release all ports */
3096 while((portlist = ea_endpoint->ep_portlist)) {
3097 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
3098 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
3099 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3100 message_put(message);
3101 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3102 ea_endpoint->free_portlist(portlist);
3105 /* disconnect audio */
3106 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3107 message->param.audiopath = 0;
3108 message_put(message);
3110 /* get dialing info */
3111 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3112 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3113 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3114 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3115 new_state(EPOINT_STATE_OUT_OVERLAP);
3118 schedule_timer(&e_redial_timeout, 1, 0);
3121 /* if we have a pending redial, so we just adjust the dialing number */
3122 if (e_redial_timeout.active) {
3123 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);
3124 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3127 if (!ea_endpoint->ep_portlist) {
3128 PERROR("ERROR: overlap dialing to a NULL port relation\n");
3130 if (ea_endpoint->ep_portlist->next) {
3131 PERROR("ERROR: overlap dialing to a port_list port relation\n");
3133 if (e_state == EPOINT_STATE_OUT_SETUP) {
3135 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);
3136 SCAT(e_dialing_queue, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3139 /* get what we have not dialed yet */
3140 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));
3141 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
3142 SCPY(message->param.information.id, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3143 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
3144 message_put(message);
3145 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3147 /* always store what we have dialed or queued */
3148 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3152 if (e_state != EPOINT_STATE_IDLE) {
3153 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
3156 /* if an internal extension is dialed, copy that number */
3157 if (param->setup.dialinginfo.itype==INFO_ITYPE_ISDN_EXTENSION || param->setup.dialinginfo.itype==INFO_ITYPE_VBOX)
3158 SCPY(e_ext.number, param->setup.dialinginfo.id);
3159 /* if an internal extension is dialed, get extension's info about caller */
3160 if (e_ext.number[0]) {
3161 if (!read_extension(&e_ext, e_ext.number)) {
3162 e_ext.number[0] = '\0';
3163 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the called terminal='%s' is not found in directory tree!\n", ea_endpoint->ep_serial, e_ext.number);
3167 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3168 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3169 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3170 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3172 /* process (voice over) data calls */
3173 if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO) {
3174 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) handling data call as audio call: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
3175 memset(&e_capainfo, 0, sizeof(e_capainfo));
3176 e_capainfo.bearer_capa = INFO_BC_AUDIO;
3177 e_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
3178 e_capainfo.bearer_info1 = (options.law=='u')?INFO_INFO1_ULAW:INFO_INFO1_ALAW;
3181 new_state(EPOINT_STATE_OUT_SETUP);
3182 /* call special setup routine */
3186 /* join MESSAGE_mISDNSIGNAL */
3187 void EndpointAppPBX::join_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param)
3189 struct lcr_msg *message;
3192 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
3193 memcpy(&message->param, param, sizeof(union parameter));
3194 message_put(message);
3195 portlist = portlist->next;
3199 /* join MESSAGE_NOTIFY */
3200 void EndpointAppPBX::join_notify(struct port_list *portlist, int message_type, union parameter *param)
3202 struct lcr_msg *message;
3205 if (param->notifyinfo.notify) {
3206 new_state = track_notify(e_tx_state, param->notifyinfo.notify);
3207 // /* if notification was generated locally, we turn hold music on/off */
3208 // if (param->notifyinfo.local)
3209 // 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)
3213 if (new_state!=NOTIFY_STATE_HOLD && new_state!=NOTIFY_STATE_SUSPEND) {
3214 if (!strcmp(e_tone, "hold")) { // don't interrupt other tones
3216 set_tone(portlist, "");
3217 portlist = portlist->next;
3220 portlist = ea_endpoint->ep_portlist;
3225 if (new_state==NOTIFY_STATE_HOLD || new_state==NOTIFY_STATE_SUSPEND) {
3227 set_tone(portlist, "hold");
3228 portlist = portlist->next;
3230 portlist = ea_endpoint->ep_portlist;
3235 /* save new state */
3236 e_tx_state = new_state;
3239 /* notify port(s) about it */
3241 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3242 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
3243 /* handle restricted caller ids */
3244 apply_callerid_restriction(&e_ext, message->param.notifyinfo.id, &message->param.notifyinfo.ntype, &message->param.notifyinfo.present, 0, message->param.notifyinfo.extension, NULL);
3245 /* display callerid if desired for extension */
3246 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));
3247 message_put(message);
3248 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3249 portlist = portlist->next;
3253 /* join MESSAGE_DTMF */
3254 void EndpointAppPBX::join_dtmf(struct port_list *portlist, int message_type, union parameter *param)
3256 struct lcr_msg *message;
3259 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DTMF);
3260 memcpy(&message->param, param, sizeof(union parameter));
3261 message_put(message);
3262 portlist = portlist->next;
3266 /* JOIN sends messages to the endpoint
3268 void EndpointAppPBX::ea_message_join(unsigned int join_id, int message_type, union parameter *param)
3270 struct port_list *portlist;
3271 struct lcr_msg *message;
3274 PERROR("EPOINT(%d) error: JOIN == NULL.\n", ea_endpoint->ep_serial);
3278 portlist = ea_endpoint->ep_portlist;
3280 /* send MESSAGE_DATA to port */
3281 if (message_type == MESSAGE_DATA) {
3282 if (join_id == ea_endpoint->ep_join_id) { // still linked with JOIN
3283 /* skip if no port relation */
3286 /* skip if more than one port relation */
3289 /* forward audio data to port */
3290 message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3295 // 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);
3296 switch(message_type) {
3297 /* JOIN SENDS TONE message */
3299 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);
3300 set_tone(portlist, param->tone.name);
3303 /* JOIN SENDS CRYPT message */
3305 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);
3306 join_crypt(portlist, message_type, param);
3309 /* JOIN sends INFORMATION message */
3310 case MESSAGE_INFORMATION:
3311 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);
3312 join_information(portlist, message_type, param);
3315 /* JOIN sends FACILITY message */
3316 case MESSAGE_FACILITY:
3317 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);
3318 join_facility(portlist, message_type, param);
3321 /* JOIN sends OVERLAP message */
3322 case MESSAGE_OVERLAP:
3323 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);
3324 if (e_state!=EPOINT_STATE_IN_SETUP
3325 && e_state!=EPOINT_STATE_IN_OVERLAP) {
3326 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3329 join_overlap(portlist, message_type, param);
3332 /* JOIN sends PROCEEDING message */
3333 case MESSAGE_PROCEEDING:
3334 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);
3335 if(e_state!=EPOINT_STATE_IN_OVERLAP) {
3336 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3339 join_proceeding(portlist, message_type, param);
3342 /* JOIN sends ALERTING message */
3343 case MESSAGE_ALERTING:
3344 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);
3345 if (e_state!=EPOINT_STATE_IN_OVERLAP
3346 && e_state!=EPOINT_STATE_IN_PROCEEDING) {
3347 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state.\n", ea_endpoint->ep_serial);
3350 join_alerting(portlist, message_type, param);
3353 /* JOIN sends CONNECT message */
3354 case MESSAGE_CONNECT:
3355 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);
3356 if (e_state!=EPOINT_STATE_IN_OVERLAP
3357 && e_state!=EPOINT_STATE_IN_PROCEEDING
3358 && e_state!=EPOINT_STATE_IN_ALERTING) {
3359 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
3362 join_connect(portlist, message_type, param);
3365 /* JOIN sends DISCONNECT/RELEASE message */
3366 case MESSAGE_DISCONNECT: /* JOIN disconnect */
3367 case MESSAGE_RELEASE: /* JOIN releases */
3368 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);
3369 join_disconnect_release(message_type, param);
3372 /* JOIN sends SETUP message */
3374 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);
3375 join_setup(portlist, message_type, param);
3378 /* JOIN sends special mISDNSIGNAL message */
3379 case MESSAGE_mISDNSIGNAL: /* isdn message to port */
3380 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);
3381 join_mISDNsignal(portlist, message_type, param);
3385 kann nach dem test gelöscht werden, da eine direkte funktion im join und im mISDN zum austausch der message existiert
3386 /* JOIN requests bchannel */
3387 case MESSAGE_BCHANNEL: /* indicates the need of own bchannel access */
3388 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);
3389 /* only one port is expected to be connected to bchannel */
3396 set_tone(portlist, NULL);
3397 message = message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3398 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3402 /* JOIN has pattern available */
3403 case MESSAGE_PATTERN: /* indicating pattern available */
3404 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);
3405 if (!e_join_pattern) {
3406 PDEBUG(DEBUG_EPOINT, "-> pattern becomes available\n");
3410 set_tone(portlist, NULL);
3411 portlist = portlist->next;
3413 /* connect our audio tx and rx (blueboxing should be possibe before connect :)*/
3414 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3415 message->param.audiopath = 1;
3416 message_put(message);
3420 /* JOIN has no pattern available */
3421 case MESSAGE_NOPATTERN: /* indicating no pattern available */
3422 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);
3423 if (e_join_pattern) {
3424 PDEBUG(DEBUG_EPOINT, "-> pattern becomes unavailable\n");
3426 /* disconnect our audio tx and rx */
3427 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3428 message->param.audiopath = 0;
3429 message_put(message);
3434 /* JOIN (dunno at the moment) */
3435 case MESSAGE_REMOTE_AUDIO:
3436 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);
3437 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3438 message->param.audiopath = param->channel;
3439 message_put(message);
3443 /* JOIN sends a notify message */
3444 case MESSAGE_NOTIFY:
3445 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);
3446 join_notify(portlist, message_type, param);
3449 /* JOIN wants keypad / dtmf */
3450 case MESSAGE_ENABLEKEYPAD:
3451 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);
3454 trace_header("ENABLE KEYPAD", DIRECTION_NONE);
3458 /* JOIN sends a DTMF message */
3460 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received dtmf.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3461 join_dtmf(portlist, message_type, param);
3465 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);
3470 /* pick_join will connect the first incoming call found. the endpoint
3471 * will receivce a MESSAGE_CONNECT.
3473 int match_list(char *list, char *item)
3475 char *end, *next = NULL;
3477 /* no list make matching */
3482 /* eliminate white spaces */
3483 while (*list <= ' ')
3489 /* if end of list is reached, we return */
3490 if (list[0] == '\0')
3492 /* if we have more than one entry (left) */
3493 if ((end = strchr(list, ',')))
3496 next = end = strchr(list, '\0');
3497 while (*(end-1) <= ' ')
3499 /* if string part matches item */
3500 if (!strncmp(list, item, end-list))
3506 void EndpointAppPBX::pick_join(char *extensions)
3508 struct lcr_msg *message;
3509 struct port_list *portlist;
3511 class EndpointAppPBX *eapp, *found;
3513 class JoinPBX *joinpbx;
3514 struct join_relation *relation;
3517 /* find an endpoint that is ringing internally or vbox with higher priority */
3520 eapp = apppbx_first;
3522 if (eapp!=this && ea_endpoint->ep_portlist) {
3523 portlist = eapp->ea_endpoint->ep_portlist;
3525 if ((port = find_port_id(portlist->port_id))) {
3526 if (port->p_type == PORT_TYPE_VBOX_OUT) {
3527 if (match_list(extensions, eapp->e_ext.number)) {
3533 if ((port->p_type==PORT_TYPE_DSS1_NT_OUT
3534 || port->p_type==PORT_TYPE_DSS1_TE_OUT
3535 || port->p_type==PORT_TYPE_GSM_BS_OUT
3536 || port->p_type==PORT_TYPE_GSM_MS_OUT)
3537 && port->p_state==PORT_STATE_OUT_ALERTING)
3538 if (match_list(extensions, eapp->e_ext.number)) {
3542 portlist = portlist->next;
3550 /* if no endpoint found */
3552 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);
3554 set_tone(ea_endpoint->ep_portlist, "cause_10");
3555 message_disconnect_port(ea_endpoint->ep_portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
3556 new_state(EPOINT_STATE_OUT_DISCONNECT);
3561 if (ea_endpoint->ep_join_id) {
3562 PERROR("EPOINT(%d) we already have a join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3565 if (!eapp->ea_endpoint->ep_join_id) {
3566 PERROR("EPOINT(%d) ringing endpoint has no join.\n", ea_endpoint->ep_serial);
3569 join = find_join_id(eapp->ea_endpoint->ep_join_id);
3571 PERROR("EPOINT(%d) ringing endpoint's join not found.\n", ea_endpoint->ep_serial);
3574 if (join->j_type != JOIN_TYPE_PBX) {
3575 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ringing endpoint's join is not a PBX join, so we must reject.\n", ea_endpoint->ep_serial);
3578 joinpbx = (class JoinPBX *)join;
3579 relation = joinpbx->j_relation;
3581 PERROR("EPOINT(%d) ringing endpoint's join has no relation. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3584 while (relation->epoint_id != eapp->ea_endpoint->ep_serial) {
3585 relation = relation->next;
3587 PERROR("EPOINT(%d) ringing endpoint's join has no relation to that join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3592 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found ringing endpoint: %d.\n", ea_endpoint->ep_serial, eapp->ea_endpoint->ep_serial);
3594 if (options.deb & DEBUG_EPOINT) {
3595 class Join *debug_c = join_first;
3596 class Endpoint *debug_e = epoint_first;
3597 class Port *debug_p = port_first;
3599 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(before)");
3601 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3603 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3604 debug_c = debug_c->next;
3606 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3608 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3609 debug_e = debug_e->next;
3611 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3613 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld (active)\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3614 debug_p = debug_p->next;
3619 ea_endpoint->ep_join_id = eapp->ea_endpoint->ep_join_id; /* we get the join */
3620 relation->epoint_id = ea_endpoint->ep_serial; /* the join gets us */
3621 eapp->ea_endpoint->ep_join_id = 0; /* the ringing endpoint will get disconnected */
3623 /* connnecting our endpoint */
3624 new_state(EPOINT_STATE_CONNECT);
3625 if (e_ext.number[0])
3627 set_tone(ea_endpoint->ep_portlist, NULL);
3629 /* now we send a release to the ringing endpoint */
3630 message = message_create(ea_endpoint->ep_join_id, eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3631 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
3632 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3633 message_put(message);
3635 /* we send a connect to the join with our caller id */
3636 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CONNECT);
3637 SCPY(message->param.connectinfo.id, e_callerinfo.id);
3638 message->param.connectinfo.present = e_callerinfo.present;
3639 message->param.connectinfo.screen = e_callerinfo.screen;
3640 message->param.connectinfo.itype = e_callerinfo.itype;
3641 message->param.connectinfo.ntype = e_callerinfo.ntype;
3642 message_put(message);
3644 /* we send a connect to our port with the remote callerid */
3645 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3646 SCPY(message->param.connectinfo.id, eapp->e_callerinfo.id);
3647 message->param.connectinfo.present = eapp->e_callerinfo.present;
3648 message->param.connectinfo.screen = eapp->e_callerinfo.screen;
3649 message->param.connectinfo.itype = eapp->e_callerinfo.itype;
3650 message->param.connectinfo.ntype = eapp->e_callerinfo.ntype;
3651 /* handle restricted caller ids */
3652 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);
3653 /* display callerid if desired for extension */
3654 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));
3655 message_put(message);
3657 /* we send a connect to the audio path (not for vbox) */
3658 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3659 message->param.audiopath = 1;
3660 message_put(message);
3662 /* beeing paranoid, we make call update */
3663 trigger_work(&joinpbx->j_updatebridge);
3665 if (options.deb & DEBUG_EPOINT) {
3666 class Join *debug_c = join_first;
3667 class Endpoint *debug_e = epoint_first;
3668 class Port *debug_p = port_first;
3670 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(after)");
3672 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3674 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3675 debug_c = debug_c->next;
3677 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3679 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3680 debug_e = debug_e->next;
3682 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3684 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3685 debug_p = debug_p->next;
3691 /* join calls (look for a join that is on hold (same isdn interface/terminal))
3693 void EndpointAppPBX::join_join(void)
3695 struct lcr_msg *message;
3696 struct join_relation *our_relation, *other_relation;
3697 struct join_relation **our_relation_pointer, **other_relation_pointer;
3698 class Join *our_join, *other_join;
3699 class JoinPBX *our_joinpbx, *other_joinpbx;
3700 class EndpointAppPBX *other_eapp; class Endpoint *temp_epoint;
3701 class Port *our_port, *other_port;
3702 class Pdss1 *our_pdss1, *other_pdss1;
3704 /* are we a candidate to join a join? */
3705 our_join = find_join_id(ea_endpoint->ep_join_id);
3707 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3710 if (our_join->j_type != JOIN_TYPE_PBX) {
3711 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: join is not a pbx join.\n", ea_endpoint->ep_serial);
3714 our_joinpbx = (class JoinPBX *)our_join;
3715 if (!ea_endpoint->ep_portlist) {
3716 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
3719 if (!e_ext.number[0]) {
3720 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
3723 our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
3725 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
3728 if ((our_port->p_type & PORT_CLASS_mISDN_MASK) != PORT_CLASS_DSS1) {
3729 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not isdn.\n", ea_endpoint->ep_serial);
3732 our_pdss1 = (class Pdss1 *)our_port;
3734 /* find an endpoint that is on hold and has the same mISDNport that we are on */
3735 other_eapp = apppbx_first;
3737 if (other_eapp == this) {
3738 other_eapp = other_eapp->next;
3741 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);
3742 if (other_eapp->e_ext.number[0] /* has terminal */
3743 && other_eapp->ea_endpoint->ep_portlist /* has port */
3744 && other_eapp->ea_endpoint->ep_join_id) { /* has join */
3745 other_port = find_port_id(other_eapp->ea_endpoint->ep_portlist->port_id);
3746 if (other_port) { /* port still exists */
3747 if (other_port->p_type==PORT_TYPE_DSS1_NT_OUT
3748 || other_port->p_type==PORT_TYPE_DSS1_NT_IN) { /* port is isdn nt-mode */
3749 other_pdss1 = (class Pdss1 *)other_port;
3750 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);
3751 if (other_pdss1->p_m_hold /* port is on hold */
3752 && other_pdss1->p_m_mISDNport == our_pdss1->p_m_mISDNport /* same isdn interface */
3753 && other_pdss1->p_m_d_ces == our_pdss1->p_m_d_ces) /* same tei+sapi */
3756 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of other type!\n", ea_endpoint->ep_serial);
3759 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port doesn't exist enymore.\n", ea_endpoint->ep_serial);
3762 other_eapp = other_eapp->next;
3765 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn terminal.\n", ea_endpoint->ep_serial);
3768 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port with same terminal found.\n", ea_endpoint->ep_serial);
3770 /* if we have the same join */
3771 if (other_eapp->ea_endpoint->ep_join_id == ea_endpoint->ep_join_id) {
3772 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we and the other have the same join.\n", ea_endpoint->ep_serial);
3775 other_join = find_join_id(other_eapp->ea_endpoint->ep_join_id);
3777 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3780 if (other_join->j_type != JOIN_TYPE_PBX) {
3781 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join is not a pbx join.\n", ea_endpoint->ep_serial);
3784 other_joinpbx = (class JoinPBX *)other_join;
3785 if (our_joinpbx->j_partyline && other_joinpbx->j_partyline) {
3786 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both joins are partylines.\n", ea_endpoint->ep_serial);
3790 /* remove relation to endpoint for join on hold */
3791 other_relation = other_joinpbx->j_relation;
3792 other_relation_pointer = &other_joinpbx->j_relation;
3793 while(other_relation) {
3794 if (other_relation->epoint_id == other_eapp->ea_endpoint->ep_serial) {
3795 /* detach other endpoint on hold */
3796 *other_relation_pointer = other_relation->next;
3797 FREE(other_relation, sizeof(struct join_relation));
3799 other_relation = *other_relation_pointer;
3800 other_eapp->ea_endpoint->ep_join_id = 0;
3804 /* change join/hold pointer of endpoint to the new join */
3805 temp_epoint = find_epoint_id(other_relation->epoint_id);
3807 if (temp_epoint->ep_join_id == other_join->j_serial)
3808 temp_epoint->ep_join_id = our_join->j_serial;
3811 other_relation_pointer = &other_relation->next;
3812 other_relation = other_relation->next;
3814 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint on hold removed, other enpoints on join relinked (to our join).\n", ea_endpoint->ep_serial);
3816 /* join call relations */
3817 our_relation = our_joinpbx->j_relation;
3818 our_relation_pointer = &our_joinpbx->j_relation;
3819 while(our_relation) {
3820 our_relation_pointer = &our_relation->next;
3821 our_relation = our_relation->next;
3823 *our_relation_pointer = other_joinpbx->j_relation;
3824 other_joinpbx->j_relation = NULL;
3825 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) relations joined.\n", ea_endpoint->ep_serial);
3827 /* release endpoint on hold */
3828 message = message_create(other_joinpbx->j_serial, other_eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3829 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */
3830 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3831 message_put(message);
3833 /* if we are not a partyline, we get partyline state from other join */
3834 our_joinpbx->j_partyline += other_joinpbx->j_partyline;
3836 /* remove empty join */
3838 PDEBUG(DEBUG_EPOINT, "EPOINT(%d)d-join completely removed!\n");
3840 /* mixer must update */
3841 trigger_work(&our_joinpbx->j_updatebridge);
3843 /* we send a retrieve to that endpoint */
3844 // mixer will update the hold-state of the join and send it to the endpoints is changes
3848 /* check if we have an external call
3849 * this is used to check for encryption ability
3851 int EndpointAppPBX::check_external(const char **errstr, class Port **port)
3853 struct join_relation *relation;
3855 class JoinPBX *joinpbx;
3856 class Endpoint *epoint;
3858 /* some paranoia check */
3859 if (!ea_endpoint->ep_portlist) {
3860 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we have no port.\n", ea_endpoint->ep_serial);
3861 *errstr = "No Call";
3864 if (!e_ext.number[0]) {
3865 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we are not internal extension.\n", ea_endpoint->ep_serial);
3866 *errstr = "No Call";
3870 /* check if we have a join with 2 parties */
3871 join = find_join_id(ea_endpoint->ep_join_id);
3873 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have currently no join.\n", ea_endpoint->ep_serial);
3874 *errstr = "No Call";
3877 if (join->j_type != JOIN_TYPE_PBX) {
3878 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join is not a pbx join.\n", ea_endpoint->ep_serial);
3879 *errstr = "No PBX Call";
3882 joinpbx = (class JoinPBX *)join;
3883 relation = joinpbx->j_relation;
3885 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no relation.\n", ea_endpoint->ep_serial);
3886 *errstr = "No Call";
3889 if (!relation->next) {
3890 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd relation.\n", ea_endpoint->ep_serial);
3891 *errstr = "No Call";
3894 if (relation->next->next) {
3895 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has more than two relations.\n", ea_endpoint->ep_serial);
3896 *errstr = "Err: Conference";
3899 if (relation->epoint_id == ea_endpoint->ep_serial) {
3900 relation = relation->next;
3901 if (relation->epoint_id == ea_endpoint->ep_serial) {
3902 PERROR("EPOINT(%d) SOFTWARE ERROR: both join relations are related to our endpoint.\n", ea_endpoint->ep_serial);
3903 *errstr = "Software Error";
3908 /* check remote port for external call */
3909 epoint = find_epoint_id(relation->epoint_id);
3911 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd endpoint.\n", ea_endpoint->ep_serial);
3912 *errstr = "No Call";
3915 if (!epoint->ep_portlist) {
3916 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not port.\n", ea_endpoint->ep_serial);
3917 *errstr = "No Call";
3920 *port = find_port_id(epoint->ep_portlist->port_id);
3922 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has an none existing port.\n", ea_endpoint->ep_serial);
3923 *errstr = "No Call";
3926 if (((*port)->p_type & PORT_CLASS_mISDN_MASK) != PORT_CLASS_DSS1) { /* port is not external isdn */
3927 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not an external port.\n", ea_endpoint->ep_serial);
3928 *errstr = "No Ext Call";
3931 if ((*port)->p_state != PORT_STATE_CONNECT) {
3932 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint's port is not in connected state.\n", ea_endpoint->ep_serial);
3933 *errstr = "No Ext Connect";
3939 void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsigned int port_id, int dir)
3941 const char *logtext = "unknown";
3944 switch(message_type) {
3946 trace_header("SETUP", dir);
3947 if (dir == DIRECTION_OUT)
3948 add_trace("to", NULL, "CH(%lu)", port_id);
3949 if (dir == DIRECTION_IN)
3950 add_trace("from", NULL, "CH(%lu)", port_id);
3951 if (param->setup.callerinfo.extension[0])
3952 add_trace("extension", NULL, "%s", param->setup.callerinfo.extension);
3953 add_trace("caller id", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype, options.national, options.international));
3954 switch(param->setup.callerinfo.present) {
3955 case INFO_PRESENT_RESTRICTED:
3956 add_trace("caller id", "present", "restricted");
3958 case INFO_PRESENT_ALLOWED:
3959 add_trace("caller id", "present", "allowed");
3962 add_trace("caller id", "present", "not available");
3964 if (param->setup.callerinfo.ntype2) {
3965 add_trace("caller id2", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id2, param->setup.callerinfo.ntype2, options.national, options.international));
3966 switch(param->setup.callerinfo.present) {
3967 case INFO_PRESENT_RESTRICTED:
3968 add_trace("caller id2", "present", "restricted");
3970 case INFO_PRESENT_ALLOWED:
3971 add_trace("caller id2", "present", "allowed");
3974 add_trace("caller id2", "present", "not available");
3977 if (param->setup.redirinfo.id[0]) {
3978 add_trace("redir'ing", "number", "%s", numberrize_callerinfo(param->setup.redirinfo.id, param->setup.redirinfo.ntype, options.national, options.international));
3979 switch(param->setup.redirinfo.present) {
3980 case INFO_PRESENT_RESTRICTED:
3981 add_trace("redir'ing", "present", "restricted");
3983 case INFO_PRESENT_ALLOWED:
3984 add_trace("redir'ing", "present", "allowed");
3987 add_trace("redir'ing", "present", "not available");
3990 if (param->setup.dialinginfo.id[0])
3991 add_trace("dialing", NULL, "%s", param->setup.dialinginfo.id);
3992 if (param->setup.dialinginfo.keypad[0])
3993 add_trace("keypad", NULL, "%s", param->setup.dialinginfo.keypad);
3994 if (param->setup.dialinginfo.display[0])
3995 add_trace("display", NULL, "%s", param->setup.dialinginfo.display);
3996 if (param->setup.dialinginfo.sending_complete)
3997 add_trace("complete", NULL, "true", param->setup.dialinginfo.sending_complete);
4001 case MESSAGE_OVERLAP:
4002 trace_header("SETUP ACKNOWLEDGE", dir);
4003 if (dir == DIRECTION_OUT)
4004 add_trace("to", NULL, "CH(%lu)", port_id);
4005 if (dir == DIRECTION_IN)
4006 add_trace("from", NULL, "CH(%lu)", port_id);
4010 case MESSAGE_PROCEEDING:
4011 trace_header("PROCEEDING", dir);
4012 if (dir == DIRECTION_OUT)
4013 add_trace("to", NULL, "CH(%lu)", port_id);
4014 if (dir == DIRECTION_IN)
4015 add_trace("from", NULL, "CH(%lu)", port_id);
4019 case MESSAGE_ALERTING:
4020 trace_header("ALERTING", dir);
4021 if (dir == DIRECTION_OUT)
4022 add_trace("to", NULL, "CH(%lu)", port_id);
4023 if (dir == DIRECTION_IN)
4024 add_trace("from", NULL, "CH(%lu)", port_id);
4028 case MESSAGE_CONNECT:
4029 trace_header("CONNECT", dir);
4030 if (dir == DIRECTION_OUT)
4031 add_trace("to", NULL, "CH(%lu)", port_id);
4032 if (dir == DIRECTION_IN)
4033 add_trace("from", NULL, "CH(%lu)", port_id);
4034 if (param->connectinfo.extension[0])
4035 add_trace("extension", NULL, "%s", param->connectinfo.extension);
4036 add_trace("connect id", "number", "%s", numberrize_callerinfo(param->connectinfo.id, param->connectinfo.ntype, options.national, options.international));
4037 switch(param->connectinfo.present) {
4038 case INFO_PRESENT_RESTRICTED:
4039 add_trace("connect id", "present", "restricted");
4041 case INFO_PRESENT_ALLOWED:
4042 add_trace("connect id", "present", "allowed");
4045 add_trace("connect id", "present", "not available");
4047 if (param->connectinfo.display[0])
4048 add_trace("display", NULL, "%s", param->connectinfo.display);
4052 case MESSAGE_DISCONNECT:
4053 case MESSAGE_RELEASE:
4054 if (message_type == MESSAGE_DISCONNECT)
4055 trace_header("DISCONNECT", dir);
4057 trace_header("RELEASE", dir);
4058 if (dir == DIRECTION_OUT)
4059 add_trace("to", NULL, "CH(%lu)", port_id);
4060 if (dir == DIRECTION_IN)
4061 add_trace("from", NULL, "CH(%lu)", port_id);
4062 add_trace("cause", "value", "%d", param->disconnectinfo.cause);
4063 switch(param->disconnectinfo.location) {
4065 add_trace("cause", "location", "0-User");
4067 case LOCATION_PRIVATE_LOCAL:
4068 add_trace("cause", "location", "1-Local-PBX");
4070 case LOCATION_PUBLIC_LOCAL:
4071 add_trace("cause", "location", "2-Local-Exchange");
4073 case LOCATION_TRANSIT:
4074 add_trace("cause", "location", "3-Transit");
4076 case LOCATION_PUBLIC_REMOTE:
4077 add_trace("cause", "location", "4-Remote-Exchange");
4079 case LOCATION_PRIVATE_REMOTE:
4080 add_trace("cause", "location", "5-Remote-PBX");
4082 case LOCATION_INTERNATIONAL:
4083 add_trace("cause", "location", "7-International-Exchange");
4085 case LOCATION_BEYOND:
4086 add_trace("cause", "location", "10-Beyond-Interworking");
4089 add_trace("cause", "location", "%d", param->disconnectinfo.location);
4091 if (param->disconnectinfo.display[0])
4092 add_trace("display", NULL, "%s", param->disconnectinfo.display);
4096 case MESSAGE_NOTIFY:
4097 switch(param->notifyinfo.notify) {
4102 logtext = "USER_SUSPENDED";
4105 logtext = "BEARER_SERVICE_CHANGED";
4108 logtext = "USER_RESUMED";
4111 logtext = "CONFERENCE_ESTABLISHED";
4114 logtext = "CONFERENCE_DISCONNECTED";
4117 logtext = "OTHER_PARTY_ADDED";
4120 logtext = "ISOLATED";
4123 logtext = "REATTACHED";
4126 logtext = "OTHER_PARTY_ISOLATED";
4129 logtext = "OTHER_PARTY_REATTACHED";
4132 logtext = "OTHER_PARTY_SPLIT";
4135 logtext = "OTHER_PARTY_DISCONNECTED";
4138 logtext = "CONFERENCE_FLOATING";
4141 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
4144 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
4147 logtext = "CALL_IS_A_WAITING_CALL";
4150 logtext = "DIVERSION_ACTIVATED";
4153 logtext = "RESERVED_CT_1";
4156 logtext = "RESERVED_CT_2";
4159 logtext = "REVERSE_CHARGING";
4162 logtext = "REMOTE_HOLD";
4165 logtext = "REMOTE_RETRIEVAL";
4168 logtext = "CALL_IS_DIVERTING";
4171 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
4175 trace_header("NOTIFY", dir);
4176 if (dir == DIRECTION_OUT)
4177 add_trace("to", NULL, "CH(%lu)", port_id);
4178 if (dir == DIRECTION_IN)
4179 add_trace("from", NULL, "CH(%lu)", port_id);
4180 if (param->notifyinfo.notify)
4181 add_trace("indicator", NULL, "%s", logtext);
4182 if (param->notifyinfo.id[0]) {
4183 add_trace("redir'on", "number", "%s", numberrize_callerinfo(param->notifyinfo.id, param->notifyinfo.ntype, options.national, options.international));
4184 switch(param->notifyinfo.present) {
4185 case INFO_PRESENT_RESTRICTED:
4186 add_trace("redir'on", "present", "restricted");
4188 case INFO_PRESENT_ALLOWED:
4189 add_trace("redir'on", "present", "allowed");
4192 add_trace("redir'on", "present", "not available");
4195 if (param->notifyinfo.display[0])
4196 add_trace("display", NULL, "%s", param->notifyinfo.display);
4200 case MESSAGE_PROGRESS:
4201 switch(param->progressinfo.progress) {
4203 logtext = "Call is not end to end ISDN";
4206 logtext = "Destination address is non-ISDN";
4209 logtext = "Origination address is non-ISDN";
4212 logtext = "Call has returned to the ISDN";
4215 logtext = "In-band info or pattern available";
4218 SPRINT(buffer, "%d", param->progressinfo.progress);
4222 trace_header("PROGRESS", dir);
4223 if (dir == DIRECTION_OUT)
4224 add_trace("to", NULL, "CH(%lu)", port_id);
4225 if (dir == DIRECTION_IN)
4226 add_trace("from", NULL, "CH(%lu)", port_id);
4227 add_trace("indicator", NULL, "%s", logtext);
4228 switch(param->progressinfo.location) {
4230 add_trace("cause", "location", "0-User");
4232 case LOCATION_PRIVATE_LOCAL:
4233 add_trace("cause", "location", "1-Local-PBX");
4235 case LOCATION_PUBLIC_LOCAL:
4236 add_trace("cause", "location", "2-Local-Exchange");
4238 case LOCATION_TRANSIT:
4239 add_trace("cause", "location", "3-Transit");
4241 case LOCATION_PUBLIC_REMOTE:
4242 add_trace("cause", "location", "4-Remote-Exchange");
4244 case LOCATION_PRIVATE_REMOTE:
4245 add_trace("cause", "location", "5-Remote-PBX");
4247 case LOCATION_INTERNATIONAL:
4248 add_trace("cause", "location", "7-International-Exchange");
4250 case LOCATION_BEYOND:
4251 add_trace("cause", "location", "10-Beyond-Interworking");
4254 add_trace("cause", "location", "%d", param->progressinfo.location);
4259 case MESSAGE_INFORMATION:
4260 trace_header("INFORMATION", dir);
4261 if (dir == DIRECTION_OUT)
4262 add_trace("to", NULL, "CH(%lu)", port_id);
4263 if (dir == DIRECTION_IN)
4264 add_trace("from", NULL, "CH(%lu)", port_id);
4265 if (param->information.id[0])
4266 add_trace("dialing", NULL, "%s", param->information.id);
4267 if (param->information.display[0])
4268 add_trace("display", NULL, "%s", param->information.display);
4269 if (param->information.sending_complete)
4270 add_trace("complete", NULL, "true", param->information.sending_complete);
4274 case MESSAGE_FACILITY:
4275 trace_header("FACILITY", dir);
4276 if (dir == DIRECTION_OUT)
4277 add_trace("to", NULL, "CH(%lu)", port_id);
4278 if (dir == DIRECTION_IN)
4279 add_trace("from", NULL, "CH(%lu)", port_id);
4284 trace_header("TONE", dir);
4285 if (dir == DIRECTION_OUT)
4286 add_trace("to", NULL, "CH(%lu)", port_id);
4287 if (dir == DIRECTION_IN)
4288 add_trace("from", NULL, "CH(%lu)", port_id);
4289 if (param->tone.name[0]) {
4290 add_trace("directory", NULL, "%s", param->tone.dir[0]?param->tone.dir:"default");
4291 add_trace("name", NULL, "%s", param->tone.name);
4293 add_trace("off", NULL, NULL);
4297 case MESSAGE_SUSPEND:
4298 case MESSAGE_RESUME:
4299 if (message_type == MESSAGE_SUSPEND)
4300 trace_header("SUSPEND", dir);
4302 trace_header("RESUME", dir);
4303 if (dir == DIRECTION_OUT)
4304 add_trace("to", NULL, "CH(%lu)", port_id);
4305 if (dir == DIRECTION_IN)
4306 add_trace("from", NULL, "CH(%lu)", port_id);
4307 if (param->parkinfo.len)
4308 add_trace("length", NULL, "%d", param->parkinfo.len);
4313 case MESSAGE_BCHANNEL:
4314 trace_header("BCHANNEL", dir);
4315 switch(param->bchannel.type) {
4316 case BCHANNEL_REQUEST:
4317 add_trace("type", NULL, "request");
4319 case BCHANNEL_ASSIGN:
4320 add_trace("type", NULL, "assign");
4322 case BCHANNEL_ASSIGN_ACK:
4323 add_trace("type", NULL, "assign_ack");
4325 case BCHANNEL_REMOVE:
4326 add_trace("type", NULL, "remove");
4328 case BCHANNEL_REMOVE_ACK:
4329 add_trace("type", NULL, "remove_ack");
4332 if (param->bchannel.addr)
4333 add_trace("address", NULL, "%x", param->bchannel.addr);
4339 PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message_type);
4343 void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cause, int location, const char *display)
4345 struct lcr_msg *message;
4349 if (!portlist->port_id)
4352 if (!e_connectedmode) {
4353 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT);
4354 message->param.disconnectinfo.cause = cause;
4355 message->param.disconnectinfo.location = location;
4357 SCPY(message->param.disconnectinfo.display, display);
4359 SCPY(message->param.disconnectinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4361 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
4363 SCPY(message->param.notifyinfo.display, display);
4365 SCPY(message->param.notifyinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4367 message_put(message);
4368 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);