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)
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_put(message);
242 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
244 ea_endpoint->free_portlist(portlist);
247 /* if callback is enabled, call back with the given caller id */
248 if (e_callback_timeout.active) {
249 /* reset some stuff */
250 new_state(EPOINT_STATE_IDLE);
251 memset(&e_connectinfo, 0, sizeof(struct connect_info));
252 memset(&e_redirinfo, 0, sizeof(struct redir_info));
253 e_start = e_stop = 0;
254 e_ruleset = ruleset_main;
256 e_rule = e_ruleset->rule_first;
258 unsched_timer(&e_action_timeout);
259 unsched_timer(&e_match_timeout);
260 unsched_timer(&e_cfnr_timeout);
261 unsched_timer(&e_cfnr_call_timeout);
262 e_match_to_action = NULL;
264 e_extdialing = e_dialinginfo.id;
270 e_multipoint_cause = 0;
271 e_multipoint_location = 0;
272 e_dialing_queue[0] = '\0';
274 e_crypt_state = CM_ST_NULL;
275 e_crypt_keyengine_busy = 0;
276 e_crypt_info[0] = '\0';
280 e_tx_state = NOTIFY_STATE_ACTIVE;
281 e_rx_state = NOTIFY_STATE_ACTIVE;
282 e_join_cause = e_join_location = 0;
284 /* the caller info of the callback user */
285 memcpy(&e_callbackinfo, &e_callerinfo, sizeof(e_callbackinfo));
286 memset(&e_dialinginfo, 0, sizeof(e_dialinginfo));
287 /* create dialing by callerinfo */
288 if (e_ext.number[0] && e_extension_interface[0]) {
289 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to internal: %s interface %s\n", ea_endpoint->ep_serial, e_ext.number, e_extension_interface);
290 /* create callback to the current terminal */
291 SCPY(e_dialinginfo.id, e_ext.number);
292 SCPY(e_dialinginfo.interfaces, e_extension_interface);
293 e_dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
294 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
297 SCPY(e_dialinginfo.id, e_cbto);
299 /* numberrize caller id and use it to dial to the callback */
300 SCPY(e_dialinginfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype, options.national, options.international));
302 e_dialinginfo.itype = INFO_ITYPE_ISDN;
303 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
304 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to external: %s\n", ea_endpoint->ep_serial, e_dialinginfo.id);
309 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release of epoint itself.\n", ea_endpoint->ep_serial);
310 if (--ea_endpoint->ep_use <= 0) /* when e_lock is 0, the endpoint will be deleted */
311 trigger_work(&ea_endpoint->ep_delete);
317 /* cancel callerid if restricted, unless anon-ignore is enabled at extension or port is of type external (so called police gets caller id :)*/
318 void apply_callerid_restriction(struct extension *ext, char *id, int *ntype, int *present, int *screen, char *extension, char *name)
320 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");
322 /* caller id is not restricted, so we do nothing */
323 if (*present != INFO_PRESENT_RESTRICTED)
326 /* only extensions are restricted */
330 /* if we enabled anonymouse ignore */
331 if (ext->anon_ignore)
334 /* else we remove the caller id */
338 *ntype = INFO_NTYPE_UNKNOWN;
340 // *screen = INFO_SCREEN_USER;
341 // maybe we should not make voip address anonymous
344 // maybe it's no fraud to present extension id
346 // extension[0] = '\0';
351 /* used display message to display callerid as available */
352 char *EndpointAppPBX::apply_callerid_display(const char *id, int itype, int ntype, int present, int screen, const char *extension, const char *name)
354 static char display[81];
357 const char *cid = numberrize_callerinfo(id, ntype, options.national, options.international);
359 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");
368 /* NOTE: is caller is is not available for this extesion, it has been removed by apply_callerid_restriction already */
370 /* internal extension's caller id */
371 if (extension[0] && e_ext.display_int) {
373 SCAT(display, extension);
376 if (itype == INFO_ITYPE_VBOX)
377 SCAT(display, "(vbox)");
379 SCAT(display, "(int)");
382 /* external caller id */
383 if (!extension[0] && e_ext.display_ext) {
386 if (present == INFO_PRESENT_RESTRICTED)
387 SCAT(display, "anonymous");
389 SCAT(display, "unknown");
396 /* display if callerid is anonymouse but available due anon-ignore */
397 if (e_ext.display_anon && present==INFO_PRESENT_RESTRICTED) {
399 SCAT(display, "unknown");
402 SCAT(display, " anon");
405 /* display if callerid is anonymouse but available due anon-ignore */
406 if (e_ext.display_fake && screen==INFO_SCREEN_USER && ntype!=INFO_NTYPE_NOTPRESENT) {
409 if (present == INFO_PRESENT_RESTRICTED)
410 SCAT(display, "anonymous");
412 SCAT(display, "unknown");
417 SCAT(display, " fake");
421 if (name[0] && e_ext.display_name) {
422 if (!display[0] && cid[0])
433 * uses the current state to notify activity
435 void EndpointAppPBX::notify_active(void)
437 struct port_list *portlist = ea_endpoint->ep_portlist;
438 struct lcr_msg *message;
442 case NOTIFY_STATE_ACTIVE:
443 /* we are already active, so we don't do anything */
446 case NOTIFY_STATE_SUSPEND:
447 notify = INFO_NOTIFY_USER_RESUMED;
449 set_tone(portlist, NULL);
450 portlist = portlist->next;
452 portlist = ea_endpoint->ep_portlist;
455 case NOTIFY_STATE_HOLD:
456 notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
458 set_tone(portlist, NULL);
459 portlist = portlist->next;
461 portlist = ea_endpoint->ep_portlist;
464 case NOTIFY_STATE_CONFERENCE:
465 notify = INFO_NOTIFY_CONFERENCE_DISCONNECTED;
467 set_tone(portlist, NULL);
468 portlist = portlist->next;
470 portlist = ea_endpoint->ep_portlist;
474 PERROR("unknown e_tx_state = %d\n", e_tx_state);
479 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
480 message->param.notifyinfo.notify = notify;
481 message_put(message);
482 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
483 portlist = portlist->next;
489 * keypad functions during call. one example to use this is to put a call on hold or start a conference
491 void EndpointAppPBX::keypad_function(char digit)
494 /* we must be in a call, in order to send messages to the call */
495 if (e_ext.number[0] == '\0') {
496 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) IGNORING keypad received not from extension.\n", ea_endpoint->ep_serial);
501 /* join conference */
503 if (ea_endpoint->ep_join_id == 0) {
504 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad received during connect but not during a call.\n", ea_endpoint->ep_serial);
507 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join call with call on hold\n", ea_endpoint->ep_serial);
513 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) shared key encryption selected.\n", ea_endpoint->ep_serial);
517 /* crypt key-exchange */
519 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) key exchange encryption selected.\n", ea_endpoint->ep_serial);
525 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) encryption off selected.\n", ea_endpoint->ep_serial);
530 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) unsupported keypad digit '%c'.\n", ea_endpoint->ep_serial, digit);
535 /* set tone pattern for port */
536 void EndpointAppPBX::set_tone(struct port_list *portlist, const char *tone)
538 struct lcr_msg *message;
543 /* store for suspended processes */
547 if (e_join_pattern /* pattern are provided */
548 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_SETUP)
549 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_OVERLAP)
550 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_IN_PROCEEDING)
551 && !(e_ext.own_alerting && e_state == EPOINT_STATE_IN_ALERTING)
552 && !(e_ext.own_cause && e_state == EPOINT_STATE_IN_DISCONNECT)
553 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_SETUP)
554 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_OVERLAP)
555 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_OUT_PROCEEDING)
556 && !(e_ext.own_alerting && e_state == EPOINT_STATE_OUT_ALERTING)
557 && !(e_ext.own_cause && e_state == EPOINT_STATE_OUT_DISCONNECT)
558 && tone[0] && !!strncmp(tone,"crypt_*",6)) {
559 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) tone not provided since patterns are available\n", ea_endpoint->ep_serial);
564 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_TONE);
565 SCPY(message->param.tone.dir, e_ext.tones_dir);
566 SCPY(message->param.tone.name, tone);
567 message_put(message);
568 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
570 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port to notify tone.\n", ea_endpoint->ep_serial);
577 * hunts an mISDNport that is available for an outgoing call
578 * if no ifname was given, any interface that is not an extension
581 struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel)
583 struct interface *interface;
584 struct interface_port *ifport, *ifport_start;
585 struct select_channel *selchannel;
586 struct mISDNport *mISDNport;
588 int there_is_an_external = 0;
590 interface = interface_first;
592 /* first find the given interface or, if not given, one with no extension */
595 if (!there_is_an_external && !(ifname && ifname[0])) {
596 trace_header("CHANNEL SELECTION (no external interface specified)", DIRECTION_NONE);
597 add_trace("info", NULL, "Add 'external' parameter to interface.conf.");
603 /* check for given interface */
604 if (ifname && ifname[0]) {
605 if (!strcasecmp(interface->name, ifname)) {
606 /* found explicit interface */
607 trace_header("CHANNEL SELECTION (found given interface)", DIRECTION_NONE);
608 add_trace("interface", NULL, "%s", ifname);
614 if (interface->external) {
615 there_is_an_external = 1;
616 /* found non extension */
617 trace_header("CHANNEL SELECTION (found external interface)", DIRECTION_NONE);
618 add_trace("interface", NULL, "%s", interface->name);
624 interface = interface->next;
628 /* see if interface has ports */
629 if (!interface->ifport) {
631 trace_header("CHANNEL SELECTION (active ports, skipping)", DIRECTION_NONE);
632 add_trace("interface", NULL, "%s", interface->name);
634 interface = interface->next;
638 /* select port by algorithm */
639 ifport_start = interface->ifport;
641 if (interface->hunt == HUNT_ROUNDROBIN) {
642 while(ifport_start->next && index<interface->hunt_next) {
643 ifport_start = ifport_start->next;
646 trace_header("CHANNEL SELECTION (starting round-robin)", DIRECTION_NONE);
647 add_trace("port", NULL, "%d", ifport_start->portnum);
648 add_trace("position", NULL, "%d", index);
653 ifport = ifport_start;
656 /* see if port is available */
657 if (!ifport->mISDNport) {
658 trace_header("CHANNEL SELECTION (port not available, skipping)", DIRECTION_NONE);
659 add_trace("port", NULL, "%d", ifport->portnum);
660 add_trace("position", NULL, "%d", index);
664 mISDNport = ifport->mISDNport;
666 /* see if port is administratively blocked */
668 trace_header("CHANNEL SELECTION (port blocked by admin, skipping)", DIRECTION_NONE);
669 add_trace("port", NULL, "%d", ifport->portnum);
670 add_trace("position", NULL, "%d", index);
675 /* see if link is up on PTP*/
676 if (mISDNport->l2hold && mISDNport->l2link<1) {
677 trace_header("CHANNEL SELECTION (port's layer 2 is down, skipping)", DIRECTION_NONE);
678 add_trace("port", NULL, "%d", ifport->portnum);
679 add_trace("position", NULL, "%d", index);
684 /* check for channel form selection list */
687 if (mISDNport->ss5) {
689 port = ss5_hunt_line(mISDNport);
691 *channel = port->p_m_b_channel;
692 trace_header("CHANNEL SELECTION (selecting SS5 channel)", DIRECTION_NONE);
693 add_trace("port", NULL, "%d", ifport->portnum);
694 add_trace("position", NULL, "%d", index);
695 add_trace("channel", NULL, "%d", *channel);
701 selchannel = ifport->out_channel;
703 switch(selchannel->channel) {
704 case CHANNEL_FREE: /* free channel */
705 if (mISDNport->b_reserved >= mISDNport->b_num)
706 break; /* all channel in use or reserverd */
709 while(i < mISDNport->b_num) {
710 if (mISDNport->b_port[i] == NULL) {
711 *channel = i+1+(i>=15);
712 trace_header("CHANNEL SELECTION (selecting free channel)", DIRECTION_NONE);
713 add_trace("port", NULL, "%d", ifport->portnum);
714 add_trace("position", NULL, "%d", index);
715 add_trace("channel", NULL, "%d", *channel);
723 trace_header("CHANNEL SELECTION (no channel is 'free')", DIRECTION_NONE);
724 add_trace("port", NULL, "%d", ifport->portnum);
725 add_trace("position", NULL, "%d", index);
729 case CHANNEL_ANY: /* don't ask for channel */
730 if (mISDNport->b_reserved >= mISDNport->b_num) {
731 trace_header("CHANNEL SELECTION (cannot ask for 'any' channel, all reserved)", DIRECTION_NONE);
732 add_trace("port", NULL, "%d", ifport->portnum);
733 add_trace("position", NULL, "%d", index);
734 add_trace("total", NULL, "%d", mISDNport->b_num);
735 add_trace("reserved", NULL, "%d", mISDNport->b_reserved);
737 break; /* all channel in use or reserverd */
739 trace_header("CHANNEL SELECTION (using 'any' channel)", DIRECTION_NONE);
740 add_trace("port", NULL, "%d", ifport->portnum);
741 add_trace("position", NULL, "%d", index);
743 *channel = CHANNEL_ANY;
746 case CHANNEL_NO: /* call waiting */
747 trace_header("CHANNEL SELECTION (using 'no' channel, call-waiting)", DIRECTION_NONE);
748 add_trace("port", NULL, "%d", ifport->portnum);
749 add_trace("position", NULL, "%d", index);
751 *channel = CHANNEL_NO;
755 if (selchannel->channel<1 || selchannel->channel==16) {
756 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
757 add_trace("port", NULL, "%d", ifport->portnum);
758 add_trace("position", NULL, "%d", index);
759 add_trace("channel", NULL, "%d", selchannel->channel);
761 break; /* invalid channels */
763 i = selchannel->channel-1-(selchannel->channel>=17);
764 if (i >= mISDNport->b_num) {
765 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
766 add_trace("port", NULL, "%d", ifport->portnum);
767 add_trace("position", NULL, "%d", index);
768 add_trace("channel", NULL, "%d", selchannel->channel);
769 add_trace("channels", NULL, "%d", mISDNport->b_num);
771 break; /* channel not in port */
773 if (mISDNport->b_port[i] == NULL) {
774 *channel = selchannel->channel;
775 trace_header("CHANNEL SELECTION (selecting given channel)", DIRECTION_NONE);
776 add_trace("port", NULL, "%d", ifport->portnum);
777 add_trace("position", NULL, "%d", index);
778 add_trace("channel", NULL, "%d", *channel);
785 break; /* found channel */
786 selchannel = selchannel->next;
790 /* if channel was found, return mISDNport and channel */
792 /* setting next port to start next time */
793 if (interface->hunt == HUNT_ROUNDROBIN) {
797 interface->hunt_next = index;
803 trace_header("CHANNEL SELECTION (skipping, no channel found)", DIRECTION_NONE);
804 add_trace("port", NULL, "%d", ifport->portnum);
805 add_trace("position", NULL, "%d", index);
809 /* go next port, until all ports are checked */
811 ifport = ifport->next;
814 ifport = interface->ifport;
816 if (ifport != ifport_start)
820 interface = interface->next;
824 return(NULL); /* no port found */
827 /* outgoing setup to port(s)
828 * ports will be created and a setup is sent if everything is ok. otherwhise
829 * the endpoint is destroyed.
831 void EndpointAppPBX::out_setup(void)
833 struct dialing_info dialinginfo;
835 struct port_list *portlist;
836 struct lcr_msg *message;
838 int cause = CAUSE_RESSOURCEUNAVAIL;
841 struct mISDNport *mISDNport;
844 class EndpointAppPBX *atemp;
845 // char allowed_ports[256];
847 char ifname[sizeof(e_ext.interfaces)],
849 struct port_settings port_settings;
852 int mode = B_MODE_TRANSPARENT;
854 /* set bchannel mode */
855 mode = e_capainfo.source_mode;
857 /* create settings for creating port */
858 memset(&port_settings, 0, sizeof(port_settings));
860 SCPY(port_settings.tones_dir, e_ext.tones_dir);
862 SCPY(port_settings.tones_dir, options.tones_dir);
863 port_settings.no_seconds = e_ext.no_seconds;
865 /* 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 */
867 /* check what dialinginfo.itype we got */
868 switch(e_dialinginfo.itype) {
869 /* *********************** call to extension or vbox */
870 case INFO_ITYPE_ISDN_EXTENSION:
871 /* check if we deny incoming calls when we use an extension */
872 if (e_ext.noknocking) {
873 atemp = apppbx_first;
876 if (!strcmp(atemp->e_ext.number, e_ext.number))
881 PERROR("EPOINT(%d) noknocking and currently a call\n", ea_endpoint->ep_serial);
882 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYSPE_ join, port */
883 return; /* must exit here */
886 /* FALL THROUGH !!!! */
887 case INFO_ITYPE_VBOX:
888 /* get dialed extension's info */
889 // SCPY(exten, e_dialinginfo.id);
890 // if (strchr(exten, ','))
891 // *strchr(exten, ',') = '\0';
892 // if (!read_extension(&e_ext, exten))
893 if (!read_extension(&e_ext, e_dialinginfo.id)) {
894 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) extension %s not configured\n", ea_endpoint->ep_serial, e_dialinginfo.id);
895 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
896 return; /* must exit here */
899 if (e_dialinginfo.itype == INFO_ITYPE_VBOX) {
900 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing directly to VBOX\n", ea_endpoint->ep_serial);
905 /* string from unconditional call forward (cfu) */
908 /* present to forwarded party */
909 if (e_ext.anon_ignore && e_callerinfo.id[0]) {
910 e_callerinfo.present = INFO_PRESENT_ALLOWED;
912 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
916 /* string from busy call forward (cfb) */
919 class EndpointAppPBX *checkapp = apppbx_first;
921 if (checkapp != this) { /* any other endpoint except our own */
922 if (!strcmp(checkapp->e_ext.number, e_ext.number)) {
923 /* present to forwarded party */
924 if (e_ext.anon_ignore && e_callerinfo.id[0]) {
925 e_callerinfo.present = INFO_PRESENT_ALLOWED;
927 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
931 checkapp = checkapp->next;
935 /* string from no-response call forward (cfnr) */
938 /* when cfnr is done, out_setup() will setup the call */
939 if (e_cfnr_call_timeout.active) {
940 /* present to forwarded party */
941 if (e_ext.anon_ignore && e_callerinfo.id[0]) {
942 e_callerinfo.present = INFO_PRESENT_ALLOWED;
946 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH)) {
947 schedule_timer(&e_cfnr_timeout, e_ext.cfnr_delay, 0);
948 schedule_timer(&e_cfnr_call_timeout, e_ext.cfnr_delay + 1, 0); /* call one second after release */
949 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);
953 /* call to all internal interfaces */
954 p = e_ext.interfaces;
955 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) generating multiple joins for extension %s to interfaces %s\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
958 while(*p!=',' && *p!='\0')
963 /* found interface */
964 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
965 /* hunt for mISDNport and create Port */
966 mISDNport = hunt_port(ifname, &channel);
968 trace_header("INTERFACE (not found or busy)", DIRECTION_NONE);
969 add_trace("interface", NULL, "%s", ifname);
973 /* creating INTERNAL port */
974 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
977 port = ss5_hunt_line(mISDNport);
981 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);
984 port = new Pgsm(PORT_TYPE_GSM_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
989 FATAL("No memory for Port instance\n");
990 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
991 memset(&dialinginfo, 0, sizeof(dialinginfo));
992 SCPY(dialinginfo.id, e_dialinginfo.id);
993 dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
994 dialinginfo.ntype = e_dialinginfo.ntype;
995 /* create port_list relation */
996 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
998 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1000 goto check_anycall_intern;
1002 /* directory.list */
1003 if (e_callerinfo.id[0] && e_ext.display_name) {
1004 dirname = parse_directory(e_callerinfo.id, e_callerinfo.ntype);
1006 SCPY(e_callerinfo.name, dirname);
1008 // dss1 = (class Pdss1 *)port;
1010 //printf("INTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1011 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1012 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1013 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1014 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1015 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1016 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1017 //terminal if (e_dialinginfo.id)
1018 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1019 /* handle restricted caller ids */
1020 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);
1021 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);
1022 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);
1023 /* display callerid if desired for extension */
1024 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));
1025 //printf("\n\ndisplay = %s\n\n\n",message->param.setup.callerinfo.display);
1026 /* use cnip, if enabld */
1027 // if (!e_ext.centrex)
1028 // message->param.setup.callerinfo.name[0] = '\0';
1029 /* screen clip if prefix is required */
1030 if (message->param.setup.callerinfo.id[0] && e_ext.clip_prefix[0]) {
1031 SCPY(message->param.setup.callerinfo.id, e_ext.clip_prefix);
1032 SCAT(message->param.setup.callerinfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype, options.national, options.international));
1033 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1035 if (message->param.setup.callerinfo.id2[0] && e_ext.clip_prefix[0]) {
1036 SCPY(message->param.setup.callerinfo.id2, e_ext.clip_prefix);
1037 SCAT(message->param.setup.callerinfo.id2, numberrize_callerinfo(e_callerinfo.id2,e_callerinfo.ntype2, options.national, options.international));
1038 message->param.setup.callerinfo.ntype2 = INFO_NTYPE_UNKNOWN;
1040 /* use internal caller id */
1041 if (e_callerinfo.extension[0] && (message->param.setup.callerinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore)) {
1042 SCPY(message->param.setup.callerinfo.id, e_callerinfo.extension);
1043 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1044 message->param.setup.callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
1046 message_put(message);
1047 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1051 /* string from parallel call forward (cfp) */
1054 if (e_ext.anon_ignore && e_callerinfo.id[0]) {
1055 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1056 e_callerinfo.present2 = INFO_PRESENT_ALLOWED;
1060 vbox_only: /* entry point for answering machine only */
1061 cfu_only: /* entry point for cfu */
1062 cfb_only: /* entry point for cfb */
1063 cfnr_only: /* entry point for cfnr */
1064 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call extension %s for external destiantion(s) '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
1068 /* only if vbox should be dialed, and terminal is given */
1069 if (!strcmp(p, "vbox") && e_ext.number[0]) {
1070 /* go to the end of p */
1073 /* answering vbox call */
1074 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) answering machine\n", ea_endpoint->ep_serial);
1076 if (!(port = new VBoxPort(PORT_TYPE_VBOX_OUT, &port_settings)))
1077 FATAL("No memory for VBOX Port instance\n");
1078 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocated port %s\n", ea_endpoint->ep_serial, port->p_name);
1079 UCPY(cfp, e_ext.number); /* cfp or any other direct forward/vbox */
1082 while(*p!=',' && *p!='\0')
1087 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cfp external %s\n", ea_endpoint->ep_serial, cfp);
1088 /* hunt for mISDNport and create Port */
1089 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1091 /* creating EXTERNAL port*/
1092 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1095 port = ss5_hunt_line(mISDNport);
1098 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);
1100 FATAL("No memory for Port instance\n");
1101 earlyb = mISDNport->earlyb;
1104 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1105 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1110 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port found or created, which is idle.\n", ea_endpoint->ep_serial);
1111 goto check_anycall_intern;
1113 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found or created port %s\n", ea_endpoint->ep_serial, port->p_name);
1114 memset(&dialinginfo, 0, sizeof(dialinginfo));
1115 SCPY(dialinginfo.id, cfp);
1116 dialinginfo.itype = INFO_ITYPE_ISDN;
1117 dialinginfo.ntype = e_dialinginfo.ntype;
1118 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
1120 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1122 goto check_anycall_intern;
1124 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1125 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1126 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1127 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1128 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1129 /* if clip is hidden */
1130 if (e_ext.clip==CLIP_HIDE && port->p_type!=PORT_TYPE_VBOX_OUT) {
1131 SCPY(message->param.setup.callerinfo.id, e_ext.callerid);
1132 SCPY(message->param.setup.callerinfo.extension, e_ext.number);
1133 message->param.setup.callerinfo.ntype = e_ext.callerid_type;
1134 message->param.setup.callerinfo.present = e_ext.callerid_present;
1135 message->param.setup.callerinfo.ntype = INFO_NTYPE_NOTPRESENT;
1137 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1138 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1139 //terminal if (e_dialinginfo.id)
1140 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1141 /* handle restricted caller ids */
1142 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);
1143 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);
1144 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);
1145 /* display callerid if desired for extension */
1146 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));
1147 message_put(message);
1148 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1152 check_anycall_intern:
1153 /* now we have all ports created */
1155 trace_header("INTERFACE (no extension's interface)", DIRECTION_NONE);
1157 if (!ea_endpoint->ep_join_id)
1159 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1160 return; /* must exit here */
1164 /* *********************** external call */
1166 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: called='%s' keypad='%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id, e_dialinginfo.keypad);
1167 /* call to extenal interfaces */
1168 if (e_dialinginfo.keypad[0])
1169 p = e_dialinginfo.keypad;
1171 p = e_dialinginfo.id;
1174 while(*p!=',' && *p!='\0')
1175 SCCAT(number, *p++);
1179 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");
1180 /* hunt for mISDNport and create Port */
1181 /* hunt for mISDNport and create Port */
1182 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1184 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1185 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1187 goto check_anycall_extern;
1189 /* creating EXTERNAL port*/
1190 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1193 port = ss5_hunt_line(mISDNport);
1196 if (!mISDNport->gsm)
1197 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);
1200 port = new Pgsm(PORT_TYPE_GSM_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
1205 FATAL("No memory for Port instance\n");
1206 earlyb = mISDNport->earlyb;
1207 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
1208 memset(&dialinginfo, 0, sizeof(dialinginfo));
1209 if (e_dialinginfo.keypad[0])
1210 SCPY(dialinginfo.keypad, number);
1212 SCPY(dialinginfo.id, number);
1213 dialinginfo.itype = INFO_ITYPE_ISDN;
1214 dialinginfo.ntype = e_dialinginfo.ntype;
1215 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
1217 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1219 goto check_anycall_extern;
1221 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1222 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1223 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1224 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1225 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1226 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1227 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1228 //terminal if (e_dialinginfo.id)
1229 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1230 /* handle restricted caller ids */
1231 apply_callerid_restriction(&e_ext, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
1232 apply_callerid_restriction(&e_ext, message->param.setup.callerinfo.id2, &message->param.setup.callerinfo.ntype2, &message->param.setup.callerinfo.present2, &message->param.setup.callerinfo.screen2, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
1233 apply_callerid_restriction(&e_ext, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, 0, message->param.setup.redirinfo.extension, NULL);
1234 /* display callerid if desired for extension */
1235 SCPY(message->param.setup.callerinfo.display, apply_callerid_display(message->param.setup.callerinfo.id, message->param.setup.callerinfo.itype, message->param.setup.callerinfo.ntype, message->param.setup.callerinfo.present, message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name));
1236 message_put(message);
1237 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1241 check_anycall_extern:
1242 /* now we have all ports created */
1244 trace_header("INTERFACE (no free ports found)", DIRECTION_NONE);
1246 if (!ea_endpoint->ep_join_id)
1248 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1249 return; /* must exit here */
1256 int action_timeout(struct lcr_timer *timer, void *instance, int index)
1258 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1260 if (!ea->e_action || ea->e_state == EPOINT_STATE_CONNECT)
1263 unsched_timer(&ea->e_redial_timeout);
1264 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current action timed out.\n", ea->ea_endpoint->ep_serial);
1265 ea->e_multipoint_cause = 0;
1266 ea->e_multipoint_location = 0;
1267 ea->new_state(EPOINT_STATE_IN_OVERLAP);
1268 ea->e_join_pattern = 0;
1269 ea->process_dialing(1);
1270 /* we must exit, because our endpoint might be gone */
1275 int match_timeout(struct lcr_timer *timer, void *instance, int index)
1277 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1279 if (!ea->e_action) {
1280 unsched_timer(&ea->e_redial_timeout);
1281 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we got a match timeout.\n", ea->ea_endpoint->ep_serial);
1282 ea->process_dialing(0);
1283 /* we must exit, because our endpoint might be gone */
1289 int redial_timeout(struct lcr_timer *timer, void *instance, int index)
1291 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1293 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial.\n", ea->ea_endpoint->ep_serial);
1295 ea->new_state(EPOINT_STATE_OUT_SETUP);
1296 /* call special setup routine */
1302 int powerdial_timeout(struct lcr_timer *timer, void *instance, int index)
1304 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1306 /* leave power dialing on */
1307 ea->e_powerdial_on = 1;
1308 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial of powerdial.\n", ea->ea_endpoint->ep_serial);
1311 ea->e_ruleset = ruleset_main;
1313 ea->e_rule = ea->e_ruleset->rule_first;
1314 ea->e_action = NULL;
1315 ea->new_state(EPOINT_STATE_IN_OVERLAP);
1316 ea->process_dialing(0);
1321 int cfnr_timeout(struct lcr_timer *timer, void *instance, int index)
1323 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1324 struct port_list *portlist;
1325 struct lcr_msg *message;
1327 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-no-response time has expired, hanging up.\n", ea->ea_endpoint->ep_serial);
1329 /* release all ports */
1330 while((portlist = ea->ea_endpoint->ep_portlist)) {
1331 message = message_create(ea->ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1332 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
1333 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1334 message_put(message);
1335 ea->logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1336 ea->ea_endpoint->free_portlist(portlist);
1339 message = message_create(ea->ea_endpoint->ep_serial, ea->ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1340 message->param.audiopath = 0;
1341 message_put(message);
1342 /* indicate no patterns */
1343 message = message_create(ea->ea_endpoint->ep_serial, ea->ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1344 message_put(message);
1345 /* set setup state, since we have no response from the new join */
1346 ea->new_state(EPOINT_STATE_OUT_SETUP);
1351 int cfnr_call_timeout(struct lcr_timer *timer, void *instance, int index)
1353 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1355 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);
1361 int callback_timeout(struct lcr_timer *timer, void *instance, int index)
1363 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1365 if (ea->e_state == EPOINT_STATE_IDLE) {
1366 /* epoint is idle, check callback */
1367 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting callback.\n", ea->ea_endpoint->ep_serial);
1368 ea->new_state(EPOINT_STATE_OUT_SETUP);
1375 int password_timeout(struct lcr_timer *timer, void *instance, int index)
1377 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1379 if (ea->e_action->index==ACTION_PASSWORD || ea->e_action->index==ACTION_PASSWORD_WRITE) {
1380 struct port_list *portlist;
1382 ea->e_ruleset = ruleset_main;
1384 ea->e_rule = ea->e_ruleset->rule_first;
1385 ea->e_action = NULL;
1386 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) password timeout %s\n", ea->ea_endpoint->ep_serial, ea->e_extdialing);
1387 ea->trace_header("PASSWORD timeout", DIRECTION_NONE);
1389 ea->e_connectedmode = 0;
1391 ea->new_state(EPOINT_STATE_OUT_DISCONNECT);
1392 portlist = ea->ea_endpoint->ep_portlist;
1394 ea->message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
1395 ea->set_tone(portlist, "cause_10");
1402 /* doing a hookflash */
1403 void EndpointAppPBX::hookflash(void)
1408 /* be sure that we are active */
1410 e_tx_state = NOTIFY_STATE_ACTIVE;
1412 trace_header("HOOKFLASH DTMF", DIRECTION_NONE);
1414 if (ea_endpoint->ep_use > 1) {
1415 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot hooflash while child process is running.\n", ea_endpoint->ep_serial);
1418 /* dialtone after pressing the hash key */
1419 process_hangup(e_join_cause, e_join_location);
1420 e_multipoint_cause = 0;
1421 e_multipoint_location = 0;
1422 port = find_port_id(ea_endpoint->ep_portlist->port_id);
1424 port->set_echotest(0);
1426 if (ea_endpoint->ep_join_id) {
1427 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1429 e_ruleset = ruleset_main;
1431 e_rule = e_ruleset->rule_first;
1433 new_state(EPOINT_STATE_IN_OVERLAP);
1434 e_connectedmode = 1;
1435 SCPY(e_dialinginfo.id, e_ext.prefix);
1436 e_extdialing = e_dialinginfo.id;
1438 if (e_dialinginfo.id[0]) {
1439 set_tone(ea_endpoint->ep_portlist, "dialing");
1442 set_tone(ea_endpoint->ep_portlist, "dialpbx");
1450 /* messages from port
1452 /* port MESSAGE_SETUP */
1453 void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, union parameter *param)
1455 struct lcr_msg *message;
1457 int writeext; /* flags need to write extension after modification */
1459 struct interface *interface;
1461 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1463 portlist->port_type = param->setup.port_type;
1464 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
1465 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
1466 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
1467 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
1469 /* convert (inter-)national number type */
1470 SCPY(e_dialinginfo.id, numberrize_callerinfo(e_dialinginfo.id, e_dialinginfo.ntype, options.national, options.international));
1471 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
1473 // e_dtmf = param->setup.dtmf;
1474 /* screen incoming caller id */
1475 interface = interface_first;
1477 if (!strcmp(e_callerinfo.interface, interface->name)) {
1480 interface = interface->next;
1483 do_screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface);
1484 do_screen(0, e_callerinfo.id2, sizeof(e_callerinfo.id2), &e_callerinfo.ntype2, &e_callerinfo.present2, interface);
1487 /* process extension */
1488 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION) {
1489 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is extension\n", ea_endpoint->ep_serial);
1490 /* port makes call from extension */
1491 SCPY(e_callerinfo.extension, e_callerinfo.id);
1492 SCPY(e_ext.number, e_callerinfo.extension);
1493 SCPY(e_extension_interface, e_callerinfo.interface);
1495 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is external or voip\n", ea_endpoint->ep_serial);
1498 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION) {
1499 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1501 /* get extension's info about caller */
1502 if (!read_extension(&e_ext, e_ext.number)) {
1503 /* extension doesn't exist */
1504 trace_header("EXTENSION (not created)", DIRECTION_IN);
1505 add_trace("extension", NULL, "%s", e_ext.number);
1507 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
1508 new_state(EPOINT_STATE_OUT_DISCONNECT);
1509 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
1510 e_ext.number[0] = '\0'; /* no terminal */
1515 /* put prefix (next) in front of e_dialinginfo.id */
1516 if (e_ext.next[0]) {
1517 SPRINT(buffer, "%s%s", e_ext.next, e_dialinginfo.id);
1518 SCPY(e_dialinginfo.id, buffer);
1519 e_ext.next[0] = '\0';
1521 } else if (e_ext.prefix[0]) {
1522 SPRINT(buffer, "%s%s", e_ext.prefix, e_dialinginfo.id);
1523 SCPY(e_dialinginfo.id, buffer);
1526 /* screen caller id by extension's config */
1527 e_callerinfo.screen = INFO_SCREEN_NETWORK;
1529 SCPY(e_callerinfo.name, e_ext.name);
1530 /* use caller id (or if exist: id_next_call) for this call */
1531 if (e_ext.id_next_call_present >= 0) {
1532 SCPY(e_callerinfo.id, e_ext.id_next_call);
1533 /* if we restrict the pesentation */
1534 if (e_ext.id_next_call_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1535 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1536 else e_callerinfo.present = e_ext.id_next_call_present;
1537 e_callerinfo.ntype = e_ext.id_next_call_type;
1538 e_ext.id_next_call_present = -1;
1541 SCPY(e_callerinfo.id, e_ext.callerid);
1542 /* if we restrict the pesentation */
1543 if (e_ext.callerid_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1544 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1545 else e_callerinfo.present = e_ext.callerid_present;
1546 e_callerinfo.ntype = e_ext.callerid_type;
1548 e_callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
1550 /* extension is written */
1552 write_extension(&e_ext, e_ext.number);
1554 /* set volume of rx and tx */
1555 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1556 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0) {
1557 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
1558 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
1559 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
1560 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
1561 message_put(message);
1564 /* start recording if enabled */
1565 if (e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO)) {
1566 /* check if we are a terminal */
1567 if (e_ext.number[0] == '\0')
1568 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
1570 port = find_port_id(portlist->port_id);
1572 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
1576 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from external port\n", ea_endpoint->ep_serial);
1577 /* no terminal identification */
1578 e_ext.number[0] = '\0';
1579 e_extension_interface[0] = '\0';
1580 memset(&e_ext, 0, sizeof(e_ext));
1581 e_ext.rights = 4; /* right to dial internat */
1585 e_ruleset = ruleset_main;
1587 e_rule = e_ruleset->rule_first;
1589 e_extdialing = e_dialinginfo.id;
1590 new_state(EPOINT_STATE_IN_SETUP);
1591 if (e_dialinginfo.id[0]) {
1592 set_tone(portlist, "dialing");
1594 if (e_ext.number[0])
1595 set_tone(portlist, "dialpbx");
1597 set_tone(portlist, "dialtone");
1600 if (e_state == EPOINT_STATE_IN_SETUP) {
1601 /* request MORE info, if not already at higher state */
1602 new_state(EPOINT_STATE_IN_OVERLAP);
1603 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_OVERLAP);
1604 message_put(message);
1605 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1609 /* port MESSAGE_INFORMATION */
1610 void EndpointAppPBX::port_information(struct port_list *portlist, int message_type, union parameter *param)
1612 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1614 /* ignore information message without digit information */
1615 if (!param->information.id[0])
1620 /* turn off dtmf detection, in case dtmf is sent with keypad information */
1622 trace_header("DTMF (disabling due to keypad)", DIRECTION_IN);
1627 /* if vbox_play is done, the information are just used as they come */
1629 if (e_action->index == ACTION_VBOX_PLAY) {
1630 /* concat dialing string */
1631 SCAT(e_dialinginfo.id, param->information.id);
1636 /* keypad when disconnect but in connected mode */
1637 if (e_state==EPOINT_STATE_OUT_DISCONNECT && e_connectedmode) {
1638 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received after disconnect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1639 /* processing keypad function */
1640 if (param->information.id[0] == '0') {
1646 /* keypad when connected */
1647 if (e_state == EPOINT_STATE_CONNECT || e_state == EPOINT_STATE_IN_ALERTING) {
1648 if (e_ext.keypad || e_enablekeypad) {
1649 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1650 /* processing keypad function */
1651 if (param->information.id[0] == '0') {
1654 if (param->information.id[0])
1655 keypad_function(param->information.id[0]);
1657 if (e_ext.number[0])
1658 trace_header("KEYPAD (not enabled by extension's settings)", DIRECTION_IN);
1660 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1665 if (e_state != EPOINT_STATE_IN_OVERLAP) {
1666 if (e_ext.number[0])
1667 trace_header("KEYPAD (ignored, not connected and not dialing)", DIRECTION_IN);
1669 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1673 if (!param->information.id[0])
1675 if (e_dialinginfo.id[0]=='\0' && !e_action) {
1676 set_tone(portlist, "dialing");
1679 if (e_action->index==ACTION_OUTDIAL
1680 || e_action->index==ACTION_EXTERNAL
1681 || e_action->index==ACTION_REMOTE) {
1683 set_tone(portlist, "dialing");
1684 else if (!e_extdialing[0])
1685 set_tone(portlist, "dialing");
1687 /* concat dialing string */
1688 SCAT(e_dialinginfo.id, param->information.id);
1692 /* port MESSAGE_DTMF */
1693 void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
1699 /* only if dtmf detection is enabled */
1701 trace_header("DTMF (disabled)", DIRECTION_IN);
1705 trace_header("DTMF", DIRECTION_IN);
1706 add_trace("digit", NULL, "%c", param->dtmf);
1710 NOTE: vbox is now handled due to overlap state
1711 /* if vbox_play is done, the dtmf digits are just used as they come */
1713 if (e_action->index == ACTION_VBOX_PLAY) {
1714 /* concat dialing string */
1715 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id)) {
1716 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1717 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1720 /* continue to process *X# sequences */
1724 /* check for *X# sequence */
1725 if (e_state == EPOINT_STATE_CONNECT || e_state == EPOINT_STATE_IN_ALERTING) {
1726 if (e_dtmf_time+3 < now) {
1727 /* the last digit was too far in the past to be a sequence */
1728 if (param->dtmf == '*')
1729 /* only start is allowed in the sequence */
1734 /* we have a sequence of digits, see what we got */
1735 if (param->dtmf == '*')
1737 else if (param->dtmf>='0' && param->dtmf<='9') {
1738 /* we need to have a star before we receive the digit of the sequence */
1739 if (e_dtmf_last == '*')
1740 e_dtmf_last = param->dtmf;
1741 } else if (param->dtmf == '#') {
1743 if (e_dtmf_last>='0' && e_dtmf_last<='9') {
1744 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf sequence *%c# detected.\n", ea_endpoint->ep_serial, e_dtmf_last);
1745 if (e_dtmf_last == '0') {
1749 /* processing keypad function */
1751 keypad_function(e_dtmf_last);
1757 /* set last time of dtmf */
1762 /* check for ## hookflash during dialing */
1764 if (e_action->index==ACTION_PASSWORD
1765 || e_action->index==ACTION_PASSWORD_WRITE)
1767 if (param->dtmf=='#') { /* current digit is '#' */
1768 if (e_state==EPOINT_STATE_IN_DISCONNECT
1769 || (e_state!=EPOINT_STATE_CONNECT && e_dtmf_time+3>=now && e_dtmf_last=='#')) { /* when disconnected, just #. when dialing, ##. */
1783 /* dialing using dtmf digit */
1784 if (e_state==EPOINT_STATE_IN_OVERLAP){ // && e_state==e_connectedmode)
1785 if (e_dialinginfo.id[0]=='\0' && !e_action) {
1786 set_tone(portlist, "dialing");
1788 /* concat dialing string */
1789 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id)) {
1790 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1791 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1797 /* port MESSAGE_CRYPT */
1798 void EndpointAppPBX::port_crypt(struct port_list *portlist, int message_type, union parameter *param)
1800 /* send crypt response to cryptman */
1801 if (param->crypt.type == CR_MESSAGE_IND)
1802 cryptman_msg2man(param->crypt.data, param->crypt.len);
1804 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
1807 /* port MESSAGE_OVERLAP */
1808 void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, union parameter *param)
1810 struct lcr_msg *message;
1812 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1814 /* signal to call tool */
1815 admin_call_response(e_adminid, ADMIN_CALL_SETUP_ACK, "", 0, 0, 0);
1817 if (e_dialing_queue[0] && portlist) {
1818 /* send what we have not dialed yet, because we had no setup complete */
1819 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing pending digits: '%s'\n", ea_endpoint->ep_serial, e_dialing_queue);
1820 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
1821 SCPY(message->param.information.id, e_dialing_queue);
1822 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
1823 message_put(message);
1824 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
1825 e_dialing_queue[0] = '\0';
1827 /* check if pattern is available */
1828 if (!ea_endpoint->ep_portlist->next && portlist->early_b) { /* one port_list relation and tones available */
1829 /* indicate patterns */
1830 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1831 message_put(message);
1833 /* connect audio, if not already */
1834 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1835 message->param.audiopath = 1;
1836 message_put(message);
1838 /* indicate no patterns */
1839 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1840 message_put(message);
1842 /* disconnect audio, if not already */
1843 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1844 message->param.audiopath = 0;
1845 message_put(message);
1847 new_state(EPOINT_STATE_OUT_OVERLAP);
1848 /* if we are in a join */
1849 if (ea_endpoint->ep_join_id) {
1850 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1851 memcpy(&message->param, param, sizeof(union parameter));
1852 message_put(message);
1856 /* port MESSAGE_PROCEEDING */
1857 void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_type, union parameter *param)
1859 struct lcr_msg *message;
1861 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1863 /* signal to call tool */
1864 admin_call_response(e_adminid, ADMIN_CALL_PROCEEDING, "", 0, 0, 0);
1866 e_state = EPOINT_STATE_OUT_PROCEEDING;
1867 /* check if pattern is availatle */
1868 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) { /* one port_list relation and tones available */
1869 /* indicate patterns */
1870 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1871 message_put(message);
1873 /* connect audio, if not already */
1874 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1875 message->param.audiopath = 1;
1876 message_put(message);
1878 /* indicate no patterns */
1879 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1880 message_put(message);
1882 /* disconnect audio, if not already */
1883 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1884 message->param.audiopath = 0;
1885 message_put(message);
1887 /* if we are in a call */
1888 if (ea_endpoint->ep_join_id) {
1889 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1890 memcpy(&message->param, param, sizeof(union parameter));
1891 message_put(message);
1895 /* port MESSAGE_ALERTING */
1896 void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type, union parameter *param)
1898 struct lcr_msg *message;
1900 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1902 /* signal to call tool */
1903 admin_call_response(e_adminid, ADMIN_CALL_ALERTING, "", 0, 0, 0);
1906 // set_tone(portlist, "hold");
1908 new_state(EPOINT_STATE_OUT_ALERTING);
1909 /* check if pattern is available */
1910 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) { /* one port_list relation and tones available */
1911 /* indicate patterns */
1912 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1913 message_put(message);
1915 /* connect audio, if not already */
1916 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1917 message->param.audiopath = 1;
1918 message_put(message);
1920 /* indicate no patterns */
1921 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1922 message_put(message);
1924 /* disconnect audio, if not already */
1925 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1926 message->param.audiopath = 0;
1927 message_put(message);
1929 /* if we are in a call */
1930 if (ea_endpoint->ep_join_id) {
1931 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1932 memcpy(&message->param, param, sizeof(union parameter));
1933 message_put(message);
1937 /* port MESSAGE_CONNECT */
1938 void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, union parameter *param)
1940 struct lcr_msg *message;
1942 unsigned int port_id = portlist->port_id;
1943 struct port_list *tportlist;
1945 struct interface *interface;
1948 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1950 /* signal to call tool */
1951 admin_call_response(e_adminid, ADMIN_CALL_CONNECT, numberrize_callerinfo(param->connectinfo.id,param->connectinfo.ntype, options.national, options.international), 0, 0, 0);
1953 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_connectinfo));
1954 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (start)\n", ea_endpoint->ep_serial);
1955 while(ea_endpoint->ep_portlist->next) { /* as long as we have at least two ports */
1956 tportlist = ea_endpoint->ep_portlist;
1957 if (tportlist->port_id == port_id) /* if the first portlist is the calling one, the second must be a different one */
1958 tportlist = tportlist->next;
1959 if (tportlist->port_id == port_id)
1960 FATAL("EPOINT(%d) this should not happen since the portlist list must not have two links to the same port - exitting.\n");
1961 message = message_create(ea_endpoint->ep_serial, tportlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1962 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
1963 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1964 message_put(message);
1965 logmessage(message->type, &message->param, tportlist->port_id, DIRECTION_OUT);
1966 ea_endpoint->free_portlist(tportlist);
1968 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (end)\n", ea_endpoint->ep_serial);
1973 /* screen incoming connected id */
1974 interface = interface_first;
1976 if (!strcmp(e_connectinfo.interface, interface->name)) {
1979 interface = interface->next;
1982 do_screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface);
1984 /* screen connected name */
1986 SCPY(e_connectinfo.name, e_ext.name);
1988 /* add internal id to colp */
1989 SCPY(e_connectinfo.extension, e_ext.number);
1991 /* we store the connected port number */
1992 SCPY(e_extension_interface, e_connectinfo.interface);
1994 /* for internal and am calls, we get the extension's id */
1995 if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE) {
1996 SCPY(e_connectinfo.id, e_ext.callerid);
1997 SCPY(e_connectinfo.extension, e_ext.number);
1998 e_connectinfo.itype = INFO_ITYPE_ISDN_EXTENSION;
1999 e_connectinfo.ntype = e_ext.callerid_type;
2000 e_connectinfo.present = e_ext.callerid_present;
2002 if (portlist->port_type==PORT_TYPE_VBOX_OUT) {
2003 e_connectinfo.itype = INFO_ITYPE_VBOX;
2004 e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2007 new_state(EPOINT_STATE_CONNECT);
2009 /* set volume of rx and tx */
2010 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0) {
2011 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2012 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2013 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
2014 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
2015 message_put(message);
2018 unsched_timer(&e_cfnr_timeout);
2019 unsched_timer(&e_cfnr_call_timeout);
2020 if (e_ext.number[0])
2021 e_dtmf = 1; /* allow dtmf */
2024 /* other calls with no caller id (or not available for the extension) and force colp */
2025 if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE) {
2026 e_connectinfo.ntype = INFO_NTYPE_NOTPRESENT;
2027 if (portlist->port_type==PORT_TYPE_DSS1_TE_OUT || portlist->port_type==PORT_TYPE_DSS1_NT_OUT || portlist->port_type==PORT_TYPE_GSM_OUT) { /* external extension answered */
2028 port = find_port_id(portlist->port_id);
2030 SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.id, &e_connectinfo.ntype, options.national, options.international));
2031 e_connectinfo.present = INFO_PRESENT_ALLOWED;
2036 /* send connect to join */
2037 if (ea_endpoint->ep_join_id) {
2038 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2039 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
2040 message_put(message);
2042 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2043 message->param.audiopath = 1;
2044 message_put(message);
2045 } else if (!e_adminid) {
2047 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have a callback, so we create a call with cbcaller: \"%s\".\n", ea_endpoint->ep_serial, e_cbcaller);
2048 SCPY(e_ext.number, e_cbcaller);
2049 new_state(EPOINT_STATE_IN_OVERLAP);
2050 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) callback from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2052 /* get extension's info about terminal */
2053 if (!read_extension(&e_ext, e_ext.number)) {
2054 /* extension doesn't exist */
2055 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2056 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
2057 new_state(EPOINT_STATE_OUT_DISCONNECT);
2058 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
2062 /* put prefix in front of e_cbdialing */
2063 SPRINT(buffer, "%s%s", e_ext.prefix, e_cbdialing);
2064 SCPY(e_dialinginfo.id, buffer);
2065 e_dialinginfo.itype = INFO_ITYPE_ISDN;
2066 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
2068 /* use caller id (or if exist: id_next_call) for this call */
2069 e_callerinfo.screen = INFO_SCREEN_NETWORK;
2070 SCPY(e_callerinfo.extension, e_ext.number);
2071 if (e_ext.id_next_call_present >= 0) {
2072 SCPY(e_callerinfo.id, e_ext.id_next_call);
2073 e_callerinfo.present = e_ext.id_next_call_present;
2074 e_callerinfo.ntype = e_ext.id_next_call_type;
2075 e_ext.id_next_call_present = -1;
2076 /* extension is written */
2077 write_extension(&e_ext, e_ext.number);
2079 SCPY(e_callerinfo.id, e_ext.callerid);
2080 e_callerinfo.present = e_ext.callerid_present;
2081 e_callerinfo.ntype = e_ext.callerid_type;
2083 e_callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
2085 e_connectedmode = 1; /* dtmf-hangup & disconnect prevention */
2088 /* check if caller id is NOT authenticated */
2089 if (!parse_callbackauth(e_ext.number, &e_callbackinfo)) {
2090 /* make call state to enter password */
2091 new_state(EPOINT_STATE_IN_OVERLAP);
2092 e_action = &action_password_write;
2093 unsched_timer(&e_match_timeout);
2094 e_match_to_action = NULL;
2095 e_dialinginfo.id[0] = '\0';
2096 e_extdialing = strchr(e_dialinginfo.id, '\0');
2097 schedule_timer(&e_password_timeout, 20, 0);
2100 /* incoming call (callback) */
2101 e_ruleset = ruleset_main;
2103 e_rule = e_ruleset->rule_first;
2105 e_extdialing = e_dialinginfo.id;
2106 if (e_dialinginfo.id[0]) {
2107 set_tone(portlist, "dialing");
2110 set_tone(portlist, "dialpbx");
2113 } else { /* testcall */
2114 set_tone(portlist, "hold");
2117 /* start recording if enabled, not when answering machine answers */
2118 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)) {
2119 /* check if we are a terminal */
2120 if (e_ext.number[0] == '\0')
2121 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
2123 port = find_port_id(portlist->port_id);
2125 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
2130 /* port MESSAGE_DISCONNECT MESSAGE_RELEASE */
2131 void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
2133 struct lcr_msg *message;
2135 unsigned int port_id = portlist->port_id;
2139 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2141 /* signal to call tool */
2142 admin_call_response(e_adminid, (message_type==MESSAGE_DISCONNECT)?ADMIN_CALL_DISCONNECT:ADMIN_CALL_RELEASE, "", param->disconnectinfo.cause, param->disconnectinfo.location, 0);
2144 //#warning does this work? only disconnect when incoming port hat not already disconnected yet?
2145 if (e_state==EPOINT_STATE_IN_DISCONNECT && message_type!=MESSAGE_RELEASE){ // || e_state==EPOINT_STATE_OUT_DISCONNECT || e_state==EPOINT_STATE_IDLE)
2146 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are already disconnected.\n", ea_endpoint->ep_serial);
2151 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);
2152 collect_cause(&e_multipoint_cause, &e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location);
2153 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new multipoint cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location);
2155 /* check if we have more than one portlist relation and we just ignore the disconnect */
2156 if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist->next) {
2157 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the disconnect was from a multipoint call. we just release that relation.\n", ea_endpoint->ep_serial);
2158 portlist = ea_endpoint->ep_portlist;
2160 if (portlist->port_id == port_id)
2162 portlist = portlist->next;
2165 FATAL("EPOINT(%d) no portlist related to the calling port.\n", ea_endpoint->ep_serial);
2166 if (message_type != MESSAGE_RELEASE) {
2167 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2168 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2169 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2170 message_put(message);
2171 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2173 ea_endpoint->free_portlist(portlist);
2174 return; /* one relation removed */
2176 if (e_state == EPOINT_STATE_CONNECT) {
2177 /* use cause from port after connect */
2178 cause = param->disconnectinfo.cause;
2179 location = param->disconnectinfo.location;
2181 /* use multipoint cause if no connect yet */
2182 if (e_multipoint_cause) {
2183 cause = e_multipoint_cause;
2184 location = e_multipoint_location;
2186 cause = CAUSE_NOUSER;
2187 location = LOCATION_PRIVATE_LOCAL;
2191 unsched_timer(&e_cfnr_timeout);
2192 unsched_timer(&e_cfnr_call_timeout);
2194 /* process hangup */
2195 process_hangup(e_join_cause, e_join_location);
2196 e_multipoint_cause = 0;
2197 e_multipoint_location = 0;
2199 if (message_type == MESSAGE_DISCONNECT) {
2200 /* tone to disconnected end */
2201 SPRINT(buffer, "cause_%02x", cause);
2202 if (ea_endpoint->ep_portlist)
2203 set_tone(ea_endpoint->ep_portlist, buffer);
2205 new_state(EPOINT_STATE_IN_DISCONNECT);
2208 if (ea_endpoint->ep_join_id) {
2209 int haspatterns = 0;
2210 /* check if pattern is available */
2211 if (ea_endpoint->ep_portlist)
2212 if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->early_b)
2213 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
2214 && message_type != MESSAGE_RELEASE) // if we release, we are done
2217 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has patterns.\n", ea_endpoint->ep_serial);
2218 /* indicate patterns */
2219 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2220 message_put(message);
2221 /* connect audio, if not already */
2222 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2223 message->param.audiopath = 1;
2224 message_put(message);
2225 /* send disconnect */
2226 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2227 memcpy(&message->param, param, sizeof(union parameter));
2228 message_put(message);
2229 /* disable encryption if disconnected */
2230 //PERROR("REMOVE ME: state =%d, %d\n", e_crypt_state, e_crypt);
2232 cryptman_message(CI_DISCONNECT_IND, NULL, 0);
2235 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
2238 if (message_type == MESSAGE_RELEASE)
2239 ea_endpoint->free_portlist(portlist);
2240 release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, callcause, portcause */
2241 return; /* must exit here */
2244 /* port MESSAGE_TIMEOUT */
2245 void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type, union parameter *param)
2249 trace_header("TIMEOUT", DIRECTION_IN);
2250 message_type = MESSAGE_DISCONNECT;
2251 switch (param->state) {
2252 case PORT_STATE_OUT_SETUP:
2253 case PORT_STATE_OUT_OVERLAP:
2254 add_trace("state", NULL, "outgoing setup/dialing");
2256 /* no user responding */
2257 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2258 return; /* must exit here */
2260 case PORT_STATE_IN_SETUP:
2261 case PORT_STATE_IN_OVERLAP:
2262 add_trace("state", NULL, "incoming setup/dialing");
2263 param->disconnectinfo.cause = CAUSE_INVALID; /* number incomplete */
2264 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2267 case PORT_STATE_OUT_PROCEEDING:
2268 add_trace("state", NULL, "outgoing proceeding");
2270 param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
2271 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2272 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2273 return; /* must exit here */
2275 case PORT_STATE_IN_PROCEEDING:
2276 add_trace("state", NULL, "incoming proceeding");
2277 param->disconnectinfo.cause = CAUSE_NOUSER;
2278 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL; /* no user responding */
2281 case PORT_STATE_OUT_ALERTING:
2282 add_trace("state", NULL, "outgoing alerting");
2284 param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
2285 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2286 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2287 return; /* must exit here */
2289 case PORT_STATE_CONNECT:
2290 add_trace("state", NULL, "connect");
2292 param->disconnectinfo.cause = CAUSE_NORMAL; /* normal */
2293 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2294 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2295 return; /* must exit here */
2297 case PORT_STATE_IN_ALERTING:
2298 add_trace("state", NULL, "incoming alerting");
2299 param->disconnectinfo.cause = CAUSE_NOANSWER;
2300 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2303 case PORT_STATE_IN_DISCONNECT:
2304 case PORT_STATE_OUT_DISCONNECT:
2305 add_trace("state", NULL, "disconnect");
2307 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
2308 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2309 return; /* must exit here */
2312 param->disconnectinfo.cause = 31; /* normal unspecified */
2313 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2316 /* release call, disconnect isdn */
2318 new_state(EPOINT_STATE_OUT_DISCONNECT);
2319 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2320 SCPY(e_tone, cause);
2322 set_tone(portlist, cause);
2323 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2324 portlist = portlist->next;
2326 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
2329 /* port MESSAGE_NOTIFY */
2330 void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, union parameter *param)
2332 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2334 struct lcr_msg *message;
2335 const char *logtext = "";
2338 /* signal to call tool */
2339 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);
2340 if (param->notifyinfo.notify) {
2341 e_rx_state = track_notify(e_rx_state, param->notifyinfo.notify);
2344 /* if we get notification from stack, local shows if we disabled/enabled audio stream */
2345 if (param->notifyinfo.local) switch(param->notifyinfo.notify) {
2346 case INFO_NOTIFY_REMOTE_HOLD:
2347 case INFO_NOTIFY_USER_SUSPENDED:
2348 /* tell call about it */
2349 if (ea_endpoint->ep_join_id) {
2350 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2351 message->param.audiopath = 0;
2352 message_put(message);
2356 case INFO_NOTIFY_REMOTE_RETRIEVAL:
2357 case INFO_NOTIFY_USER_RESUMED:
2358 /* set volume of rx and tx */
2359 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
2360 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
2362 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2363 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2364 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
2365 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
2366 message_put(message);
2368 /* set current tone */
2370 set_tone(portlist, e_tone);
2371 /* tell call about it */
2372 if (ea_endpoint->ep_join_id) {
2373 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2374 message->param.audiopath = 1;
2375 message_put(message);
2380 /* get name of notify */
2381 switch(param->notifyinfo.notify) {
2386 logtext = "USER_SUSPENDED";
2389 logtext = "BEARER_SERVICE_CHANGED";
2392 logtext = "USER_RESUMED";
2395 logtext = "CONFERENCE_ESTABLISHED";
2398 logtext = "CONFERENCE_DISCONNECTED";
2401 logtext = "OTHER_PARTY_ADDED";
2404 logtext = "ISOLATED";
2407 logtext = "REATTACHED";
2410 logtext = "OTHER_PARTY_ISOLATED";
2413 logtext = "OTHER_PARTY_REATTACHED";
2416 logtext = "OTHER_PARTY_SPLIT";
2419 logtext = "OTHER_PARTY_DISCONNECTED";
2422 logtext = "CONFERENCE_FLOATING";
2425 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
2428 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
2431 logtext = "CALL_IS_A_WAITING_CALL";
2434 logtext = "DIVERSION_ACTIVATED";
2437 logtext = "RESERVED_CT_1";
2440 logtext = "RESERVED_CT_2";
2443 logtext = "REVERSE_CHARGING";
2446 logtext = "REMOTE_HOLD";
2449 logtext = "REMOTE_RETRIEVAL";
2452 logtext = "CALL_IS_DIVERTING";
2455 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
2460 /* notify call if available */
2461 if (ea_endpoint->ep_join_id) {
2462 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOTIFY);
2463 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
2464 message_put(message);
2469 /* port MESSAGE_FACILITY */
2470 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
2472 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2474 struct lcr_msg *message;
2476 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_FACILITY);
2477 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2478 message_put(message);
2481 /* port MESSAGE_SUSPEND */
2482 /* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
2483 void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
2485 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2487 /* epoint is now parked */
2488 ea_endpoint->ep_park = 1;
2489 memcpy(ea_endpoint->ep_park_callid, param->parkinfo.callid, sizeof(ea_endpoint->ep_park_callid));
2490 ea_endpoint->ep_park_len = (param->parkinfo.len>8)?8:param->parkinfo.len;
2492 /* remove port relation */
2493 ea_endpoint->free_portlist(portlist);
2496 /* port MESSAGE_RESUME */
2497 /* NOTE: before resume, the active-notification must be done in order to set call mixer */
2498 void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
2500 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2502 /* epoint is now resumed */
2503 ea_endpoint->ep_park = 0;
2508 /* port sends message to the endpoint
2510 void EndpointAppPBX::ea_message_port(unsigned int port_id, int message_type, union parameter *param)
2512 struct port_list *portlist;
2514 portlist = ea_endpoint->ep_portlist;
2516 if (port_id == portlist->port_id)
2518 portlist = portlist->next;
2521 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);
2525 // PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
2526 switch(message_type) {
2527 case MESSAGE_DATA: /* data from port */
2528 /* check if there is a call */
2529 if (!ea_endpoint->ep_join_id)
2531 /* continue if only one portlist */
2532 if (ea_endpoint->ep_portlist->next != NULL)
2534 /* forward message */
2535 message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2538 case MESSAGE_TONE_EOF: /* tone is end of file */
2539 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
2541 if (e_action->index == ACTION_VBOX_PLAY) {
2544 if (e_action->index == ACTION_EFI) {
2550 case MESSAGE_TONE_COUNTER: /* counter info received */
2551 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);
2553 if (e_action->index == ACTION_VBOX_PLAY) {
2554 e_vbox_counter = param->counter.current;
2555 if (param->counter.max >= 0)
2556 e_vbox_counter_max = param->counter.max;
2560 /* PORT sends SETUP message */
2562 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);
2563 if (e_state!=EPOINT_STATE_IDLE) {
2564 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
2567 port_setup(portlist, message_type, param);
2570 /* PORT sends INFORMATION message */
2571 case MESSAGE_INFORMATION: /* additional digits received */
2572 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);
2573 port_information(portlist, message_type, param);
2576 /* PORT sends FACILITY message */
2577 case MESSAGE_FACILITY:
2578 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2579 port_facility(portlist, message_type, param);
2582 /* PORT sends DTMF message */
2583 case MESSAGE_DTMF: /* dtmf digits received */
2584 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);
2585 port_dtmf(portlist, message_type, param);
2588 /* PORT sends CRYPT message */
2589 case MESSAGE_CRYPT: /* crypt response received */
2590 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) crypt response=%d\n", ea_endpoint->ep_serial, param->crypt.type);
2591 port_crypt(portlist, message_type, param);
2594 /* PORT sends MORE message */
2595 case MESSAGE_OVERLAP:
2596 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);
2597 if (e_state != EPOINT_STATE_OUT_SETUP) {
2598 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);
2601 port_overlap(portlist, message_type, param);
2604 /* PORT sends PROCEEDING message */
2605 case MESSAGE_PROCEEDING: /* port is proceeding */
2606 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);
2607 if (e_state!=EPOINT_STATE_OUT_SETUP
2608 && e_state!=EPOINT_STATE_OUT_OVERLAP) {
2609 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);
2612 port_proceeding(portlist, message_type, param);
2615 /* PORT sends ALERTING message */
2616 case MESSAGE_ALERTING:
2617 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);
2618 if (e_state!=EPOINT_STATE_OUT_SETUP
2619 && e_state!=EPOINT_STATE_OUT_OVERLAP
2620 && e_state!=EPOINT_STATE_OUT_PROCEEDING) {
2621 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);
2624 port_alerting(portlist, message_type, param);
2627 /* PORT sends CONNECT message */
2628 case MESSAGE_CONNECT:
2629 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);
2630 if (e_state!=EPOINT_STATE_OUT_SETUP
2631 && e_state!=EPOINT_STATE_OUT_OVERLAP
2632 && e_state!=EPOINT_STATE_OUT_PROCEEDING
2633 && e_state!=EPOINT_STATE_OUT_ALERTING) {
2634 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
2637 port_connect(portlist, message_type, param);
2640 /* PORT sends DISCONNECT message */
2641 case MESSAGE_DISCONNECT: /* port is disconnected */
2642 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);
2643 port_disconnect_release(portlist, message_type, param);
2646 /* PORT sends a RELEASE message */
2647 case MESSAGE_RELEASE: /* port releases */
2648 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);
2649 /* portlist is release at port_disconnect_release, thanx Paul */
2650 port_disconnect_release(portlist, message_type, param);
2653 /* PORT sends a TIMEOUT message */
2654 case MESSAGE_TIMEOUT:
2655 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);
2656 port_timeout(portlist, message_type, param);
2657 break; /* release */
2659 /* PORT sends a NOTIFY message */
2660 case MESSAGE_NOTIFY:
2661 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);
2662 port_notify(portlist, message_type, param);
2665 /* PORT sends a SUSPEND message */
2666 case MESSAGE_SUSPEND:
2667 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);
2668 port_suspend(portlist, message_type, param);
2669 break; /* suspend */
2671 /* PORT sends a RESUME message */
2672 case MESSAGE_RESUME:
2673 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);
2674 port_resume(portlist, message_type, param);
2678 kann nach dem test gelöscht werden, da eine direkte funktion im join und im mISDN zum austausch der message existiert
2679 /* port assigns bchannel */
2680 case MESSAGE_BCHANNEL: /* bchannel assignment messafe */
2681 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);
2682 /* only one port is expected to be connected to bchannel */
2683 message = message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2684 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_IN);
2690 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);
2693 /* Note: this endpoint may be destroyed, so we MUST return */
2697 /* messages from join
2699 /* join MESSAGE_CRYPT */
2700 void EndpointAppPBX::join_crypt(struct port_list *portlist, int message_type, union parameter *param)
2702 switch(param->crypt.type) {
2703 /* message from remote port to "crypt manager" */
2704 case CU_ACTK_REQ: /* activate key-exchange */
2705 case CU_ACTS_REQ: /* activate shared key */
2706 case CU_DACT_REQ: /* deactivate */
2707 case CU_INFO_REQ: /* request last info message */
2708 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2711 /* message from "crypt manager" to user */
2712 case CU_ACTK_CONF: /* key-echange done */
2713 case CU_ACTS_CONF: /* shared key done */
2714 case CU_DACT_CONF: /* deactivated */
2715 case CU_DACT_IND: /* deactivated */
2716 case CU_ERROR_IND: /* receive error message */
2717 case CU_INFO_IND: /* receive info message */
2718 case CU_INFO_CONF: /* receive info message */
2719 encrypt_result(param->crypt.type, (char *)param->crypt.data);
2723 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);
2727 /* join MESSAGE_INFORMATION */
2728 void EndpointAppPBX::join_information(struct port_list *portlist, int message_type, union parameter *param)
2730 struct lcr_msg *message;
2735 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2736 memcpy(&message->param.information, ¶m->information, sizeof(struct dialing_info));
2737 message_put(message);
2738 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2739 portlist = portlist->next;
2743 /* join MESSAGE_FACILITY */
2744 void EndpointAppPBX::join_facility(struct port_list *portlist, int message_type, union parameter *param)
2746 struct lcr_msg *message;
2748 if (!e_ext.facility && e_ext.number[0]) {
2753 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_FACILITY);
2754 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2755 message_put(message);
2756 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2757 portlist = portlist->next;
2761 /* join MESSAGE_MORE */
2762 void EndpointAppPBX::join_overlap(struct port_list *portlist, int message_type, union parameter *param)
2764 struct lcr_msg *message;
2766 new_state(EPOINT_STATE_IN_OVERLAP);
2769 if (e_join_pattern && e_ext.own_setup) {
2770 /* disconnect audio */
2771 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2772 message->param.audiopath = 0;
2773 message_put(message);
2775 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL) {
2776 if (e_dialinginfo.id[0])
2777 set_tone(portlist, "dialing");
2779 set_tone(portlist, "dialtone");
2782 if (e_dialinginfo.id[0]) {
2783 set_tone(portlist, "dialing");
2785 if (e_ext.number[0])
2786 set_tone(portlist, "dialpbx");
2788 set_tone(portlist, "dialtone");
2792 /* join MESSAGE_PROCEEDING */
2793 void EndpointAppPBX::join_proceeding(struct port_list *portlist, int message_type, union parameter *param)
2795 struct lcr_msg *message;
2797 new_state(EPOINT_STATE_IN_PROCEEDING);
2799 /* own proceeding tone */
2800 if (e_join_pattern) {
2801 /* connect / disconnect audio */
2802 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2803 if (e_ext.own_proceeding)
2804 message->param.audiopath = 0;
2806 message->param.audiopath = 1;
2807 message_put(message);
2809 // UCPY(e_join_tone, "proceeding");
2811 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
2812 message_put(message);
2813 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2815 set_tone(portlist, "proceeding");
2818 /* join MESSAGE_ALERTING */
2819 void EndpointAppPBX::join_alerting(struct port_list *portlist, int message_type, union parameter *param)
2821 struct lcr_msg *message;
2823 new_state(EPOINT_STATE_IN_ALERTING);
2825 /* own alerting tone */
2826 if (e_join_pattern) {
2827 /* connect / disconnect audio */
2828 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2829 if (e_ext.own_alerting)
2830 message->param.audiopath = 0;
2832 message->param.audiopath = 1;
2833 message_put(message);
2836 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
2837 message_put(message);
2838 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2840 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL) {
2841 set_tone(portlist, "ringing");
2844 if (e_ext.number[0])
2845 set_tone(portlist, "ringpbx");
2847 set_tone(portlist, "ringing");
2849 if (e_ext.number[0])
2850 e_dtmf = 1; /* allow dtmf */
2853 /* join MESSAGE_CONNECT */
2854 void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type, union parameter *param)
2856 struct lcr_msg *message;
2859 new_state(EPOINT_STATE_CONNECT);
2860 // UCPY(e_join_tone, "");
2862 if (e_ext.number[0])
2863 e_dtmf = 1; /* allow dtmf */
2866 unsched_timer(&e_powerdial_timeout);
2867 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_callerinfo));
2869 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
2870 memcpy(&message->param, param, sizeof(union parameter));
2872 /* screen clip if prefix is required */
2873 if (e_ext.number[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0]) {
2874 SCPY(message->param.connectinfo.id, e_ext.clip_prefix);
2875 SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype, options.national, options.international));
2876 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2879 /* use internal caller id */
2880 if (e_ext.number[0] && e_connectinfo.extension[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore)) {
2881 SCPY(message->param.connectinfo.id, e_connectinfo.extension);
2882 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2885 /* handle restricted caller ids */
2886 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);
2887 /* display callerid if desired for extension */
2888 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));
2890 /* use conp, if enabld */
2891 // if (!e_ext.centrex)
2892 // message->param.connectinfo.name[0] = '\0';
2895 message_put(message);
2896 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2898 set_tone(portlist, NULL);
2900 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2901 message->param.audiopath = 1;
2902 message_put(message);
2907 /* join MESSAGE_DISCONNECT MESSAGE_RELEASE */
2908 void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *param)
2911 struct lcr_msg *message;
2912 struct port_list *portlist = NULL;
2916 /* be sure that we are active */
2918 e_tx_state = NOTIFY_STATE_ACTIVE;
2920 /* we are powerdialing, if e_powerdial_on is set and limit is not exceeded if given */
2921 if (e_powerdial_on && ((e_powercount+1)<e_powerlimit || e_powerlimit<1)) {
2922 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
2924 /* set time for power dialing */
2925 schedule_timer(&e_powerdial_timeout, (int)e_powerdelay, 0); /* set redial in the future */
2928 /* set redial tone */
2929 if (ea_endpoint->ep_portlist) {
2932 set_tone(ea_endpoint->ep_portlist, "redial");
2933 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);
2934 /* send proceeding when powerdialing and still setup (avoid dialing timeout) */
2935 if (e_state==EPOINT_STATE_IN_OVERLAP) {
2936 new_state(EPOINT_STATE_IN_PROCEEDING);
2937 if (ea_endpoint->ep_portlist) {
2938 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
2939 message_put(message);
2940 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
2942 /* caused the error, that the first knock sound was not there */
2943 /* set_tone(portlist, "proceeding"); */
2945 /* send display of powerdialing */
2946 if (e_ext.display_dialing) {
2947 portlist = ea_endpoint->ep_portlist;
2949 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
2951 SPRINT(message->param.notifyinfo.display, "Retry %d of %d", e_powercount, e_powerlimit);
2953 SPRINT(message->param.notifyinfo.display, "Retry %d", e_powercount);
2954 message_put(message);
2955 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2956 portlist = portlist->next;
2966 if ((e_state!=EPOINT_STATE_CONNECT
2967 && e_state!=EPOINT_STATE_OUT_DISCONNECT
2968 && e_state!=EPOINT_STATE_IN_OVERLAP
2969 && e_state!=EPOINT_STATE_IN_PROCEEDING
2970 && e_state!=EPOINT_STATE_IN_ALERTING)
2971 || !ea_endpoint->ep_portlist) { /* or no port */
2972 process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
2973 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause); /* RELEASE_TYPE, join, port */
2974 return; /* must exit here */
2977 if (!e_join_cause) {
2978 e_join_cause = param->disconnectinfo.cause;
2979 e_join_location = param->disconnectinfo.location;
2982 /* on release we need the audio again! */
2983 if (message_type == MESSAGE_RELEASE) {
2985 ea_endpoint->ep_join_id = 0;
2987 /* disconnect and select tone */
2988 new_state(EPOINT_STATE_OUT_DISCONNECT);
2989 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2990 /* if own_cause, we must release the join */
2991 if (e_ext.own_cause /* own cause */
2992 || !e_join_pattern) { /* no patterns */
2993 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);
2994 if (message_type != MESSAGE_RELEASE)
2995 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
2997 } else { /* else we enable audio */
2998 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2999 message->param.audiopath = 1;
3000 message_put(message);
3002 /* send disconnect message */
3003 SCPY(e_tone, cause);
3004 portlist = ea_endpoint->ep_portlist;
3006 set_tone(portlist, cause);
3007 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
3008 portlist = portlist->next;
3012 /* join MESSAGE_SETUP */
3013 void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, union parameter *param)
3015 struct lcr_msg *message;
3016 // struct interface *interface;
3018 /* if we already in setup state, we just update the dialing with new digits */
3019 if (e_state == EPOINT_STATE_OUT_SETUP
3020 || e_state == EPOINT_STATE_OUT_OVERLAP) {
3021 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we are in setup state, so we do overlap dialing.\n", ea_endpoint->ep_serial);
3022 /* if digits changed, what we have already dialed */
3023 if (!!strncmp(e_dialinginfo.id,param->setup.dialinginfo.id,strlen(e_dialinginfo.id))) {
3024 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);
3025 /* release all ports */
3026 while((portlist = ea_endpoint->ep_portlist)) {
3027 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
3028 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
3029 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3030 message_put(message);
3031 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3032 ea_endpoint->free_portlist(portlist);
3035 /* disconnect audio */
3036 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3037 message->param.audiopath = 0;
3038 message_put(message);
3040 /* get dialing info */
3041 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3042 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3043 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3044 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3045 new_state(EPOINT_STATE_OUT_OVERLAP);
3048 schedule_timer(&e_redial_timeout, 1, 0);
3051 /* if we have a pending redial, so we just adjust the dialing number */
3052 if (e_redial_timeout.active) {
3053 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);
3054 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3057 if (!ea_endpoint->ep_portlist) {
3058 PERROR("ERROR: overlap dialing to a NULL port relation\n");
3060 if (ea_endpoint->ep_portlist->next) {
3061 PERROR("ERROR: overlap dialing to a port_list port relation\n");
3063 if (e_state == EPOINT_STATE_OUT_SETUP) {
3065 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);
3066 SCAT(e_dialing_queue, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3069 /* get what we have not dialed yet */
3070 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));
3071 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
3072 SCPY(message->param.information.id, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3073 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
3074 message_put(message);
3075 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3077 /* always store what we have dialed or queued */
3078 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3082 if (e_state != EPOINT_STATE_IDLE) {
3083 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
3086 /* if an internal extension is dialed, copy that number */
3087 if (param->setup.dialinginfo.itype==INFO_ITYPE_ISDN_EXTENSION || param->setup.dialinginfo.itype==INFO_ITYPE_VBOX)
3088 SCPY(e_ext.number, param->setup.dialinginfo.id);
3089 /* if an internal extension is dialed, get extension's info about caller */
3090 if (e_ext.number[0]) {
3091 if (!read_extension(&e_ext, e_ext.number)) {
3092 e_ext.number[0] = '\0';
3093 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the called terminal='%s' is not found in directory tree!\n", ea_endpoint->ep_serial, e_ext.number);
3097 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3098 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3099 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3100 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3102 /* process (voice over) data calls */
3103 if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO) {
3104 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) handling data call as audio call: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
3105 memset(&e_capainfo, 0, sizeof(e_capainfo));
3106 e_capainfo.bearer_capa = INFO_BC_AUDIO;
3107 e_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
3108 e_capainfo.bearer_info1 = (options.law=='u')?INFO_INFO1_ULAW:INFO_INFO1_ALAW;
3111 new_state(EPOINT_STATE_OUT_SETUP);
3112 /* call special setup routine */
3116 /* join MESSAGE_mISDNSIGNAL */
3117 void EndpointAppPBX::join_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param)
3119 struct lcr_msg *message;
3122 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
3123 memcpy(&message->param, param, sizeof(union parameter));
3124 message_put(message);
3125 portlist = portlist->next;
3129 /* join MESSAGE_NOTIFY */
3130 void EndpointAppPBX::join_notify(struct port_list *portlist, int message_type, union parameter *param)
3132 struct lcr_msg *message;
3135 if (param->notifyinfo.notify) {
3136 new_state = track_notify(e_tx_state, param->notifyinfo.notify);
3137 // /* if notification was generated locally, we turn hold music on/off */
3138 // if (param->notifyinfo.local)
3139 // 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)
3143 if (new_state!=NOTIFY_STATE_HOLD && new_state!=NOTIFY_STATE_SUSPEND) {
3144 if (!strcmp(e_tone, "hold")) { // don't interrupt other tones
3146 set_tone(portlist, "");
3147 portlist = portlist->next;
3150 portlist = ea_endpoint->ep_portlist;
3155 if (new_state==NOTIFY_STATE_HOLD || new_state==NOTIFY_STATE_SUSPEND) {
3157 set_tone(portlist, "hold");
3158 portlist = portlist->next;
3160 portlist = ea_endpoint->ep_portlist;
3165 /* save new state */
3166 e_tx_state = new_state;
3169 /* notify port(s) about it */
3171 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3172 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
3173 /* handle restricted caller ids */
3174 apply_callerid_restriction(&e_ext, message->param.notifyinfo.id, &message->param.notifyinfo.ntype, &message->param.notifyinfo.present, 0, message->param.notifyinfo.extension, NULL);
3175 /* display callerid if desired for extension */
3176 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));
3177 message_put(message);
3178 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3179 portlist = portlist->next;
3183 /* JOIN sends messages to the endpoint
3185 void EndpointAppPBX::ea_message_join(unsigned int join_id, int message_type, union parameter *param)
3187 struct port_list *portlist;
3188 struct lcr_msg *message;
3191 PERROR("EPOINT(%d) error: JOIN == NULL.\n", ea_endpoint->ep_serial);
3195 portlist = ea_endpoint->ep_portlist;
3197 /* send MESSAGE_DATA to port */
3198 if (message_type == MESSAGE_DATA) {
3199 if (join_id == ea_endpoint->ep_join_id) { // still linked with JOIN
3200 /* skip if no port relation */
3203 /* skip if more than one port relation */
3206 /* forward audio data to port */
3207 message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3212 // 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);
3213 switch(message_type) {
3214 /* JOIN SENDS TONE message */
3216 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);
3217 set_tone(portlist, param->tone.name);
3220 /* JOIN SENDS CRYPT message */
3222 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);
3223 join_crypt(portlist, message_type, param);
3226 /* JOIN sends INFORMATION message */
3227 case MESSAGE_INFORMATION:
3228 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);
3229 join_information(portlist, message_type, param);
3232 /* JOIN sends FACILITY message */
3233 case MESSAGE_FACILITY:
3234 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);
3235 join_facility(portlist, message_type, param);
3238 /* JOIN sends OVERLAP message */
3239 case MESSAGE_OVERLAP:
3240 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);
3241 if (e_state!=EPOINT_STATE_IN_SETUP
3242 && e_state!=EPOINT_STATE_IN_OVERLAP) {
3243 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3246 join_overlap(portlist, message_type, param);
3249 /* JOIN sends PROCEEDING message */
3250 case MESSAGE_PROCEEDING:
3251 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);
3252 if(e_state!=EPOINT_STATE_IN_OVERLAP) {
3253 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3256 join_proceeding(portlist, message_type, param);
3259 /* JOIN sends ALERTING message */
3260 case MESSAGE_ALERTING:
3261 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);
3262 if (e_state!=EPOINT_STATE_IN_OVERLAP
3263 && e_state!=EPOINT_STATE_IN_PROCEEDING) {
3264 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state.\n", ea_endpoint->ep_serial);
3267 join_alerting(portlist, message_type, param);
3270 /* JOIN sends CONNECT message */
3271 case MESSAGE_CONNECT:
3272 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);
3273 if (e_state!=EPOINT_STATE_IN_OVERLAP
3274 && e_state!=EPOINT_STATE_IN_PROCEEDING
3275 && e_state!=EPOINT_STATE_IN_ALERTING) {
3276 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
3279 join_connect(portlist, message_type, param);
3282 /* JOIN sends DISCONNECT/RELEASE message */
3283 case MESSAGE_DISCONNECT: /* JOIN disconnect */
3284 case MESSAGE_RELEASE: /* JOIN releases */
3285 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);
3286 join_disconnect_release(message_type, param);
3289 /* JOIN sends SETUP message */
3291 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);
3292 join_setup(portlist, message_type, param);
3295 /* JOIN sends special mISDNSIGNAL message */
3296 case MESSAGE_mISDNSIGNAL: /* isdn message to port */
3297 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);
3298 join_mISDNsignal(portlist, message_type, param);
3302 kann nach dem test gelöscht werden, da eine direkte funktion im join und im mISDN zum austausch der message existiert
3303 /* JOIN requests bchannel */
3304 case MESSAGE_BCHANNEL: /* indicates the need of own bchannel access */
3305 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);
3306 /* only one port is expected to be connected to bchannel */
3313 set_tone(portlist, NULL);
3314 message = message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3315 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3319 /* JOIN has pattern available */
3320 case MESSAGE_PATTERN: /* indicating pattern available */
3321 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);
3322 if (!e_join_pattern) {
3323 PDEBUG(DEBUG_EPOINT, "-> pattern becomes available\n");
3327 set_tone(portlist, NULL);
3328 portlist = portlist->next;
3330 /* connect our audio tx and rx (blueboxing should be possibe before connect :)*/
3331 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3332 message->param.audiopath = 1;
3333 message_put(message);
3337 /* JOIN has no pattern available */
3338 case MESSAGE_NOPATTERN: /* indicating no pattern available */
3339 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);
3340 if (e_join_pattern) {
3341 PDEBUG(DEBUG_EPOINT, "-> pattern becomes unavailable\n");
3343 /* disconnect our audio tx and rx */
3344 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3345 message->param.audiopath = 0;
3346 message_put(message);
3351 /* JOIN (dunno at the moment) */
3352 case MESSAGE_REMOTE_AUDIO:
3353 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);
3354 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3355 message->param.audiopath = param->channel;
3356 message_put(message);
3360 /* JOIN sends a notify message */
3361 case MESSAGE_NOTIFY:
3362 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);
3363 join_notify(portlist, message_type, param);
3366 /* JOIN wants keypad / dtmf */
3367 case MESSAGE_ENABLEKEYPAD:
3368 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);
3371 trace_header("ENABLE KEYPAD", DIRECTION_NONE);
3376 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);
3381 /* pick_join will connect the first incoming call found. the endpoint
3382 * will receivce a MESSAGE_CONNECT.
3384 int match_list(char *list, char *item)
3386 char *end, *next = NULL;
3388 /* no list make matching */
3393 /* eliminate white spaces */
3394 while (*list <= ' ')
3400 /* if end of list is reached, we return */
3401 if (list[0] == '\0')
3403 /* if we have more than one entry (left) */
3404 if ((end = strchr(list, ',')))
3407 next = end = strchr(list, '\0');
3408 while (*(end-1) <= ' ')
3410 /* if string part matches item */
3411 if (!strncmp(list, item, end-list))
3417 void EndpointAppPBX::pick_join(char *extensions)
3419 struct lcr_msg *message;
3420 struct port_list *portlist;
3422 class EndpointAppPBX *eapp, *found;
3424 class JoinPBX *joinpbx;
3425 struct join_relation *relation;
3428 /* find an endpoint that is ringing internally or vbox with higher priority */
3431 eapp = apppbx_first;
3433 if (eapp!=this && ea_endpoint->ep_portlist) {
3434 portlist = eapp->ea_endpoint->ep_portlist;
3436 if ((port = find_port_id(portlist->port_id))) {
3437 if (port->p_type == PORT_TYPE_VBOX_OUT) {
3438 if (match_list(extensions, eapp->e_ext.number)) {
3444 if ((port->p_type==PORT_TYPE_DSS1_NT_OUT || port->p_type==PORT_TYPE_DSS1_TE_OUT || port->p_type==PORT_TYPE_GSM_OUT)
3445 && port->p_state==PORT_STATE_OUT_ALERTING)
3446 if (match_list(extensions, eapp->e_ext.number)) {
3450 portlist = portlist->next;
3458 /* if no endpoint found */
3460 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);
3462 set_tone(ea_endpoint->ep_portlist, "cause_10");
3463 message_disconnect_port(ea_endpoint->ep_portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
3464 new_state(EPOINT_STATE_OUT_DISCONNECT);
3469 if (ea_endpoint->ep_join_id) {
3470 PERROR("EPOINT(%d) we already have a join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3473 if (!eapp->ea_endpoint->ep_join_id) {
3474 PERROR("EPOINT(%d) ringing endpoint has no join.\n", ea_endpoint->ep_serial);
3477 join = find_join_id(eapp->ea_endpoint->ep_join_id);
3479 PERROR("EPOINT(%d) ringing endpoint's join not found.\n", ea_endpoint->ep_serial);
3482 if (join->j_type != JOIN_TYPE_PBX) {
3483 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ringing endpoint's join is not a PBX join, so we must reject.\n", ea_endpoint->ep_serial);
3486 joinpbx = (class JoinPBX *)join;
3487 relation = joinpbx->j_relation;
3489 PERROR("EPOINT(%d) ringing endpoint's join has no relation. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3492 while (relation->epoint_id != eapp->ea_endpoint->ep_serial) {
3493 relation = relation->next;
3495 PERROR("EPOINT(%d) ringing endpoint's join has no relation to that join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3500 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found ringing endpoint: %d.\n", ea_endpoint->ep_serial, eapp->ea_endpoint->ep_serial);
3502 if (options.deb & DEBUG_EPOINT) {
3503 class Join *debug_c = join_first;
3504 class Endpoint *debug_e = epoint_first;
3505 class Port *debug_p = port_first;
3507 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(before)");
3509 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3511 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3512 debug_c = debug_c->next;
3514 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3516 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3517 debug_e = debug_e->next;
3519 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3521 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld (active)\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3522 debug_p = debug_p->next;
3527 ea_endpoint->ep_join_id = eapp->ea_endpoint->ep_join_id; /* we get the join */
3528 relation->epoint_id = ea_endpoint->ep_serial; /* the join gets us */
3529 eapp->ea_endpoint->ep_join_id = 0; /* the ringing endpoint will get disconnected */
3531 /* connnecting our endpoint */
3532 new_state(EPOINT_STATE_CONNECT);
3533 if (e_ext.number[0])
3535 set_tone(ea_endpoint->ep_portlist, NULL);
3537 /* now we send a release to the ringing endpoint */
3538 message = message_create(ea_endpoint->ep_join_id, eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3539 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
3540 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3541 message_put(message);
3543 /* we send a connect to the join with our caller id */
3544 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CONNECT);
3545 SCPY(message->param.connectinfo.id, e_callerinfo.id);
3546 message->param.connectinfo.present = e_callerinfo.present;
3547 message->param.connectinfo.screen = e_callerinfo.screen;
3548 message->param.connectinfo.itype = e_callerinfo.itype;
3549 message->param.connectinfo.ntype = e_callerinfo.ntype;
3550 message_put(message);
3552 /* we send a connect to our port with the remote callerid */
3553 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3554 SCPY(message->param.connectinfo.id, eapp->e_callerinfo.id);
3555 message->param.connectinfo.present = eapp->e_callerinfo.present;
3556 message->param.connectinfo.screen = eapp->e_callerinfo.screen;
3557 message->param.connectinfo.itype = eapp->e_callerinfo.itype;
3558 message->param.connectinfo.ntype = eapp->e_callerinfo.ntype;
3559 /* handle restricted caller ids */
3560 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);
3561 /* display callerid if desired for extension */
3562 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));
3563 message_put(message);
3565 /* we send a connect to the audio path (not for vbox) */
3566 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3567 message->param.audiopath = 1;
3568 message_put(message);
3570 /* beeing paranoid, we make call update */
3571 trigger_work(&joinpbx->j_updatebridge);
3573 if (options.deb & DEBUG_EPOINT) {
3574 class Join *debug_c = join_first;
3575 class Endpoint *debug_e = epoint_first;
3576 class Port *debug_p = port_first;
3578 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(after)");
3580 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3582 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3583 debug_c = debug_c->next;
3585 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3587 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3588 debug_e = debug_e->next;
3590 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3592 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3593 debug_p = debug_p->next;
3599 /* join calls (look for a join that is on hold (same isdn interface/terminal))
3601 void EndpointAppPBX::join_join(void)
3603 struct lcr_msg *message;
3604 struct join_relation *our_relation, *other_relation;
3605 struct join_relation **our_relation_pointer, **other_relation_pointer;
3606 class Join *our_join, *other_join;
3607 class JoinPBX *our_joinpbx, *other_joinpbx;
3608 class EndpointAppPBX *other_eapp; class Endpoint *temp_epoint;
3609 class Port *our_port, *other_port;
3610 class Pdss1 *our_pdss1, *other_pdss1;
3612 /* are we a candidate to join a join? */
3613 our_join = find_join_id(ea_endpoint->ep_join_id);
3615 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3618 if (our_join->j_type != JOIN_TYPE_PBX) {
3619 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: join is not a pbx join.\n", ea_endpoint->ep_serial);
3622 our_joinpbx = (class JoinPBX *)our_join;
3623 if (!ea_endpoint->ep_portlist) {
3624 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
3627 if (!e_ext.number[0]) {
3628 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
3631 our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
3633 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
3636 if ((our_port->p_type&PORT_CLASS_mISDN_MASK) != PORT_CLASS_mISDN_DSS1) {
3637 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not isdn.\n", ea_endpoint->ep_serial);
3640 our_pdss1 = (class Pdss1 *)our_port;
3642 /* find an endpoint that is on hold and has the same mISDNport that we are on */
3643 other_eapp = apppbx_first;
3645 if (other_eapp == this) {
3646 other_eapp = other_eapp->next;
3649 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);
3650 if (other_eapp->e_ext.number[0] /* has terminal */
3651 && other_eapp->ea_endpoint->ep_portlist /* has port */
3652 && other_eapp->ea_endpoint->ep_join_id) { /* has join */
3653 other_port = find_port_id(other_eapp->ea_endpoint->ep_portlist->port_id);
3654 if (other_port) { /* port still exists */
3655 if (other_port->p_type==PORT_TYPE_DSS1_NT_OUT
3656 || other_port->p_type==PORT_TYPE_DSS1_NT_IN) { /* port is isdn nt-mode */
3657 other_pdss1 = (class Pdss1 *)other_port;
3658 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);
3659 if (other_pdss1->p_m_hold /* port is on hold */
3660 && other_pdss1->p_m_mISDNport == our_pdss1->p_m_mISDNport /* same isdn interface */
3661 && other_pdss1->p_m_d_ces == our_pdss1->p_m_d_ces) /* same tei+sapi */
3664 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of other type!\n", ea_endpoint->ep_serial);
3667 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port doesn't exist enymore.\n", ea_endpoint->ep_serial);
3670 other_eapp = other_eapp->next;
3673 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn terminal.\n", ea_endpoint->ep_serial);
3676 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port with same terminal found.\n", ea_endpoint->ep_serial);
3678 /* if we have the same join */
3679 if (other_eapp->ea_endpoint->ep_join_id == ea_endpoint->ep_join_id) {
3680 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we and the other have the same join.\n", ea_endpoint->ep_serial);
3683 other_join = find_join_id(other_eapp->ea_endpoint->ep_join_id);
3685 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3688 if (other_join->j_type != JOIN_TYPE_PBX) {
3689 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join is not a pbx join.\n", ea_endpoint->ep_serial);
3692 other_joinpbx = (class JoinPBX *)other_join;
3693 if (our_joinpbx->j_partyline && other_joinpbx->j_partyline) {
3694 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both joins are partylines.\n", ea_endpoint->ep_serial);
3698 /* remove relation to endpoint for join on hold */
3699 other_relation = other_joinpbx->j_relation;
3700 other_relation_pointer = &other_joinpbx->j_relation;
3701 while(other_relation) {
3702 if (other_relation->epoint_id == other_eapp->ea_endpoint->ep_serial) {
3703 /* detach other endpoint on hold */
3704 *other_relation_pointer = other_relation->next;
3705 FREE(other_relation, sizeof(struct join_relation));
3707 other_relation = *other_relation_pointer;
3708 other_eapp->ea_endpoint->ep_join_id = 0;
3712 /* change join/hold pointer of endpoint to the new join */
3713 temp_epoint = find_epoint_id(other_relation->epoint_id);
3715 if (temp_epoint->ep_join_id == other_join->j_serial)
3716 temp_epoint->ep_join_id = our_join->j_serial;
3719 other_relation_pointer = &other_relation->next;
3720 other_relation = other_relation->next;
3722 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint on hold removed, other enpoints on join relinked (to our join).\n", ea_endpoint->ep_serial);
3724 /* join call relations */
3725 our_relation = our_joinpbx->j_relation;
3726 our_relation_pointer = &our_joinpbx->j_relation;
3727 while(our_relation) {
3728 our_relation_pointer = &our_relation->next;
3729 our_relation = our_relation->next;
3731 *our_relation_pointer = other_joinpbx->j_relation;
3732 other_joinpbx->j_relation = NULL;
3733 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) relations joined.\n", ea_endpoint->ep_serial);
3735 /* release endpoint on hold */
3736 message = message_create(other_joinpbx->j_serial, other_eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3737 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */
3738 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3739 message_put(message);
3741 /* if we are not a partyline, we get partyline state from other join */
3742 our_joinpbx->j_partyline += other_joinpbx->j_partyline;
3744 /* remove empty join */
3746 PDEBUG(DEBUG_EPOINT, "EPOINT(%d)d-join completely removed!\n");
3748 /* mixer must update */
3749 trigger_work(&our_joinpbx->j_updatebridge);
3751 /* we send a retrieve to that endpoint */
3752 // mixer will update the hold-state of the join and send it to the endpoints is changes
3756 /* check if we have an external call
3757 * this is used to check for encryption ability
3759 int EndpointAppPBX::check_external(const char **errstr, class Port **port)
3761 struct join_relation *relation;
3763 class JoinPBX *joinpbx;
3764 class Endpoint *epoint;
3766 /* some paranoia check */
3767 if (!ea_endpoint->ep_portlist) {
3768 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we have no port.\n", ea_endpoint->ep_serial);
3769 *errstr = "No Call";
3772 if (!e_ext.number[0]) {
3773 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we are not internal extension.\n", ea_endpoint->ep_serial);
3774 *errstr = "No Call";
3778 /* check if we have a join with 2 parties */
3779 join = find_join_id(ea_endpoint->ep_join_id);
3781 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have currently no join.\n", ea_endpoint->ep_serial);
3782 *errstr = "No Call";
3785 if (join->j_type != JOIN_TYPE_PBX) {
3786 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join is not a pbx join.\n", ea_endpoint->ep_serial);
3787 *errstr = "No PBX Call";
3790 joinpbx = (class JoinPBX *)join;
3791 relation = joinpbx->j_relation;
3793 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no relation.\n", ea_endpoint->ep_serial);
3794 *errstr = "No Call";
3797 if (!relation->next) {
3798 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd relation.\n", ea_endpoint->ep_serial);
3799 *errstr = "No Call";
3802 if (relation->next->next) {
3803 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has more than two relations.\n", ea_endpoint->ep_serial);
3804 *errstr = "Err: Conference";
3807 if (relation->epoint_id == ea_endpoint->ep_serial) {
3808 relation = relation->next;
3809 if (relation->epoint_id == ea_endpoint->ep_serial) {
3810 PERROR("EPOINT(%d) SOFTWARE ERROR: both join relations are related to our endpoint.\n", ea_endpoint->ep_serial);
3811 *errstr = "Software Error";
3816 /* check remote port for external call */
3817 epoint = find_epoint_id(relation->epoint_id);
3819 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd endpoint.\n", ea_endpoint->ep_serial);
3820 *errstr = "No Call";
3823 if (!epoint->ep_portlist) {
3824 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not port.\n", ea_endpoint->ep_serial);
3825 *errstr = "No Call";
3828 *port = find_port_id(epoint->ep_portlist->port_id);
3830 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has an none existing port.\n", ea_endpoint->ep_serial);
3831 *errstr = "No Call";
3834 if (((*port)->p_type&PORT_CLASS_mISDN_MASK)!=PORT_CLASS_mISDN_DSS1) { /* port is not external isdn */
3835 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not an external port.\n", ea_endpoint->ep_serial);
3836 *errstr = "No Ext Call";
3839 if ((*port)->p_state != PORT_STATE_CONNECT) {
3840 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint's port is not in connected state.\n", ea_endpoint->ep_serial);
3841 *errstr = "No Ext Connect";
3847 void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsigned int port_id, int dir)
3849 const char *logtext = "unknown";
3852 switch(message_type) {
3854 trace_header("SETUP", dir);
3855 if (dir == DIRECTION_OUT)
3856 add_trace("to", NULL, "CH(%lu)", port_id);
3857 if (dir == DIRECTION_IN)
3858 add_trace("from", NULL, "CH(%lu)", port_id);
3859 if (param->setup.callerinfo.extension[0])
3860 add_trace("extension", NULL, "%s", param->setup.callerinfo.extension);
3861 add_trace("caller id", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype, options.national, options.international));
3862 switch(param->setup.callerinfo.present) {
3863 case INFO_PRESENT_RESTRICTED:
3864 add_trace("caller id", "present", "restricted");
3866 case INFO_PRESENT_ALLOWED:
3867 add_trace("caller id", "present", "allowed");
3870 add_trace("caller id", "present", "not available");
3872 if (param->setup.callerinfo.ntype2) {
3873 add_trace("caller id2", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id2, param->setup.callerinfo.ntype2, options.national, options.international));
3874 switch(param->setup.callerinfo.present) {
3875 case INFO_PRESENT_RESTRICTED:
3876 add_trace("caller id2", "present", "restricted");
3878 case INFO_PRESENT_ALLOWED:
3879 add_trace("caller id2", "present", "allowed");
3882 add_trace("caller id2", "present", "not available");
3885 if (param->setup.redirinfo.id[0]) {
3886 add_trace("redir'ing", "number", "%s", numberrize_callerinfo(param->setup.redirinfo.id, param->setup.redirinfo.ntype, options.national, options.international));
3887 switch(param->setup.redirinfo.present) {
3888 case INFO_PRESENT_RESTRICTED:
3889 add_trace("redir'ing", "present", "restricted");
3891 case INFO_PRESENT_ALLOWED:
3892 add_trace("redir'ing", "present", "allowed");
3895 add_trace("redir'ing", "present", "not available");
3898 if (param->setup.dialinginfo.id[0])
3899 add_trace("dialing", NULL, "%s", param->setup.dialinginfo.id);
3900 if (param->setup.dialinginfo.keypad[0])
3901 add_trace("keypad", NULL, "%s", param->setup.dialinginfo.keypad);
3902 if (param->setup.dialinginfo.display[0])
3903 add_trace("display", NULL, "%s", param->setup.dialinginfo.display);
3904 if (param->setup.dialinginfo.sending_complete)
3905 add_trace("complete", NULL, "true", param->setup.dialinginfo.sending_complete);
3909 case MESSAGE_OVERLAP:
3910 trace_header("SETUP ACKNOWLEDGE", dir);
3911 if (dir == DIRECTION_OUT)
3912 add_trace("to", NULL, "CH(%lu)", port_id);
3913 if (dir == DIRECTION_IN)
3914 add_trace("from", NULL, "CH(%lu)", port_id);
3918 case MESSAGE_PROCEEDING:
3919 trace_header("PROCEEDING", dir);
3920 if (dir == DIRECTION_OUT)
3921 add_trace("to", NULL, "CH(%lu)", port_id);
3922 if (dir == DIRECTION_IN)
3923 add_trace("from", NULL, "CH(%lu)", port_id);
3927 case MESSAGE_ALERTING:
3928 trace_header("ALERTING", dir);
3929 if (dir == DIRECTION_OUT)
3930 add_trace("to", NULL, "CH(%lu)", port_id);
3931 if (dir == DIRECTION_IN)
3932 add_trace("from", NULL, "CH(%lu)", port_id);
3936 case MESSAGE_CONNECT:
3937 trace_header("CONNECT", dir);
3938 if (dir == DIRECTION_OUT)
3939 add_trace("to", NULL, "CH(%lu)", port_id);
3940 if (dir == DIRECTION_IN)
3941 add_trace("from", NULL, "CH(%lu)", port_id);
3942 if (param->connectinfo.extension[0])
3943 add_trace("extension", NULL, "%s", param->connectinfo.extension);
3944 add_trace("connect id", "number", "%s", numberrize_callerinfo(param->connectinfo.id, param->connectinfo.ntype, options.national, options.international));
3945 switch(param->connectinfo.present) {
3946 case INFO_PRESENT_RESTRICTED:
3947 add_trace("connect id", "present", "restricted");
3949 case INFO_PRESENT_ALLOWED:
3950 add_trace("connect id", "present", "allowed");
3953 add_trace("connect id", "present", "not available");
3955 if (param->connectinfo.display[0])
3956 add_trace("display", NULL, "%s", param->connectinfo.display);
3960 case MESSAGE_DISCONNECT:
3961 case MESSAGE_RELEASE:
3962 if (message_type == MESSAGE_DISCONNECT)
3963 trace_header("DISCONNECT", dir);
3965 trace_header("RELEASE", dir);
3966 if (dir == DIRECTION_OUT)
3967 add_trace("to", NULL, "CH(%lu)", port_id);
3968 if (dir == DIRECTION_IN)
3969 add_trace("from", NULL, "CH(%lu)", port_id);
3970 add_trace("cause", "value", "%d", param->disconnectinfo.cause);
3971 switch(param->disconnectinfo.location) {
3973 add_trace("cause", "location", "0-User");
3975 case LOCATION_PRIVATE_LOCAL:
3976 add_trace("cause", "location", "1-Local-PBX");
3978 case LOCATION_PUBLIC_LOCAL:
3979 add_trace("cause", "location", "2-Local-Exchange");
3981 case LOCATION_TRANSIT:
3982 add_trace("cause", "location", "3-Transit");
3984 case LOCATION_PUBLIC_REMOTE:
3985 add_trace("cause", "location", "4-Remote-Exchange");
3987 case LOCATION_PRIVATE_REMOTE:
3988 add_trace("cause", "location", "5-Remote-PBX");
3990 case LOCATION_INTERNATIONAL:
3991 add_trace("cause", "location", "7-International-Exchange");
3993 case LOCATION_BEYOND:
3994 add_trace("cause", "location", "10-Beyond-Interworking");
3997 add_trace("cause", "location", "%d", param->disconnectinfo.location);
3999 if (param->disconnectinfo.display[0])
4000 add_trace("display", NULL, "%s", param->disconnectinfo.display);
4004 case MESSAGE_NOTIFY:
4005 switch(param->notifyinfo.notify) {
4010 logtext = "USER_SUSPENDED";
4013 logtext = "BEARER_SERVICE_CHANGED";
4016 logtext = "USER_RESUMED";
4019 logtext = "CONFERENCE_ESTABLISHED";
4022 logtext = "CONFERENCE_DISCONNECTED";
4025 logtext = "OTHER_PARTY_ADDED";
4028 logtext = "ISOLATED";
4031 logtext = "REATTACHED";
4034 logtext = "OTHER_PARTY_ISOLATED";
4037 logtext = "OTHER_PARTY_REATTACHED";
4040 logtext = "OTHER_PARTY_SPLIT";
4043 logtext = "OTHER_PARTY_DISCONNECTED";
4046 logtext = "CONFERENCE_FLOATING";
4049 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
4052 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
4055 logtext = "CALL_IS_A_WAITING_CALL";
4058 logtext = "DIVERSION_ACTIVATED";
4061 logtext = "RESERVED_CT_1";
4064 logtext = "RESERVED_CT_2";
4067 logtext = "REVERSE_CHARGING";
4070 logtext = "REMOTE_HOLD";
4073 logtext = "REMOTE_RETRIEVAL";
4076 logtext = "CALL_IS_DIVERTING";
4079 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
4083 trace_header("NOTIFY", dir);
4084 if (dir == DIRECTION_OUT)
4085 add_trace("to", NULL, "CH(%lu)", port_id);
4086 if (dir == DIRECTION_IN)
4087 add_trace("from", NULL, "CH(%lu)", port_id);
4088 if (param->notifyinfo.notify)
4089 add_trace("indicator", NULL, "%s", logtext);
4090 if (param->notifyinfo.id[0]) {
4091 add_trace("redir'on", "number", "%s", numberrize_callerinfo(param->notifyinfo.id, param->notifyinfo.ntype, options.national, options.international));
4092 switch(param->notifyinfo.present) {
4093 case INFO_PRESENT_RESTRICTED:
4094 add_trace("redir'on", "present", "restricted");
4096 case INFO_PRESENT_ALLOWED:
4097 add_trace("redir'on", "present", "allowed");
4100 add_trace("redir'on", "present", "not available");
4103 if (param->notifyinfo.display[0])
4104 add_trace("display", NULL, "%s", param->notifyinfo.display);
4108 case MESSAGE_INFORMATION:
4109 trace_header("INFORMATION", dir);
4110 if (dir == DIRECTION_OUT)
4111 add_trace("to", NULL, "CH(%lu)", port_id);
4112 if (dir == DIRECTION_IN)
4113 add_trace("from", NULL, "CH(%lu)", port_id);
4114 if (param->information.id[0])
4115 add_trace("dialing", NULL, "%s", param->information.id);
4116 if (param->information.display[0])
4117 add_trace("display", NULL, "%s", param->information.display);
4118 if (param->information.sending_complete)
4119 add_trace("complete", NULL, "true", param->information.sending_complete);
4123 case MESSAGE_FACILITY:
4124 trace_header("FACILITY", dir);
4125 if (dir == DIRECTION_OUT)
4126 add_trace("to", NULL, "CH(%lu)", port_id);
4127 if (dir == DIRECTION_IN)
4128 add_trace("from", NULL, "CH(%lu)", port_id);
4133 trace_header("TONE", dir);
4134 if (dir == DIRECTION_OUT)
4135 add_trace("to", NULL, "CH(%lu)", port_id);
4136 if (dir == DIRECTION_IN)
4137 add_trace("from", NULL, "CH(%lu)", port_id);
4138 if (param->tone.name[0]) {
4139 add_trace("directory", NULL, "%s", param->tone.dir[0]?param->tone.dir:"default");
4140 add_trace("name", NULL, "%s", param->tone.name);
4142 add_trace("off", NULL, NULL);
4146 case MESSAGE_SUSPEND:
4147 case MESSAGE_RESUME:
4148 if (message_type == MESSAGE_SUSPEND)
4149 trace_header("SUSPEND", dir);
4151 trace_header("RESUME", dir);
4152 if (dir == DIRECTION_OUT)
4153 add_trace("to", NULL, "CH(%lu)", port_id);
4154 if (dir == DIRECTION_IN)
4155 add_trace("from", NULL, "CH(%lu)", port_id);
4156 if (param->parkinfo.len)
4157 add_trace("length", NULL, "%d", param->parkinfo.len);
4162 case MESSAGE_BCHANNEL:
4163 trace_header("BCHANNEL", dir);
4164 switch(param->bchannel.type) {
4165 case BCHANNEL_REQUEST:
4166 add_trace("type", NULL, "request");
4168 case BCHANNEL_ASSIGN:
4169 add_trace("type", NULL, "assign");
4171 case BCHANNEL_ASSIGN_ACK:
4172 add_trace("type", NULL, "assign_ack");
4174 case BCHANNEL_REMOVE:
4175 add_trace("type", NULL, "remove");
4177 case BCHANNEL_REMOVE_ACK:
4178 add_trace("type", NULL, "remove_ack");
4181 if (param->bchannel.addr)
4182 add_trace("address", NULL, "%x", param->bchannel.addr);
4188 PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message_type);
4192 void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cause, int location, const char *display)
4194 struct lcr_msg *message;
4198 if (!portlist->port_id)
4201 if (!e_connectedmode) {
4202 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT);
4203 message->param.disconnectinfo.cause = cause;
4204 message->param.disconnectinfo.location = location;
4206 SCPY(message->param.disconnectinfo.display, display);
4208 SCPY(message->param.disconnectinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4210 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
4212 SCPY(message->param.notifyinfo.display, display);
4214 SCPY(message->param.notifyinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4216 message_put(message);
4217 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);