1 /*****************************************************************************\
3 ** Linux Call Router **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
8 ** The EndpointAppPBX implements PBX4Linux **
10 \*****************************************************************************/
15 class EndpointAppPBX *apppbx_first = NULL;
18 * EndpointAppPBX constructor
20 EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint, int origin) : EndpointApp(epoint, origin)
22 class EndpointAppPBX **apppointer;
24 /* add application to chain */
26 apppointer = &apppbx_first;
28 apppointer = &((*apppointer)->next);
32 memset(&e_ext, 0, sizeof(struct extension));
33 // *************** NOTE: also change value in read_extension() **************
34 e_ext.rights = 4; /* international */
35 e_ext.rx_gain = e_ext.tx_gain = 0;
36 e_state = EPOINT_STATE_IDLE;
37 e_ext.number[0] = '\0';
38 e_extension_interface[0] = '\0';
39 memset(&e_callerinfo, 0, sizeof(struct caller_info));
40 memset(&e_dialinginfo, 0, sizeof(struct dialing_info));
41 memset(&e_connectinfo, 0, sizeof(struct connect_info));
42 memset(&e_redirinfo, 0, sizeof(struct redir_info));
43 memset(&e_capainfo, 0, sizeof(struct capa_info));
46 e_ruleset = ruleset_main;
48 e_rule = e_ruleset->rule_first;
53 e_match_to_action = NULL;
55 e_extdialing = e_dialinginfo.id;
59 // e_join_tone[0] = e_hold_tone[0] = '\0';
60 e_join_pattern /*= e_hold_pattern*/ = 0;
63 e_adminid = 0; // will be set, if call was initiated via admin socket
68 e_cbdialing[0] = '\0';
71 memset(&e_callbackinfo, 0, sizeof(struct caller_info));
79 e_password_timeout = 0;
80 e_multipoint_cause = 0;
81 e_multipoint_location = 0;
82 e_dialing_queue[0] = '\0';
84 e_crypt_state = CM_ST_NULL;
85 e_crypt_keyengine_busy = 0;
86 e_crypt_info[0] = '\0';
89 e_tx_state = NOTIFY_STATE_ACTIVE;
90 e_rx_state = NOTIFY_STATE_ACTIVE;
91 e_join_cause = e_join_location = 0;
92 /*********************************
93 *********************************
94 ********* ATTENTION *************
95 *********************************
96 *********************************/
97 /* if you add new values, that must be initialized, also check if they must
98 * be initialized when doing callback
104 * EpointAppPBX destructor
106 EndpointAppPBX::~EndpointAppPBX(void)
108 class EndpointAppPBX *temp, **tempp;
112 tempp = &apppbx_first;
121 FATAL("Endpoint not in endpoint's list.\n");
128 * trace header for application
130 void EndpointAppPBX::trace_header(const char *name, int direction)
134 char msgtext[sizeof(_trace.name)];
138 /* init trace with given values */
141 numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype, options.national, options.international),
145 ea_endpoint->ep_serial,
152 /* set new endpoint state
154 void EndpointAppPBX::new_state(int state)
157 if (e_state != state) {
158 trace_header("NEW STATE", DIRECTION_NONE);
159 add_trace("state", "old", "%s", state_name[e_state]);
160 add_trace("state", "new", "%s", state_name[state]);
168 /* release join and port (as specified)
170 void EndpointAppPBX::release(int release, int joinlocation, int joincause, int portlocation, int portcause)
172 struct port_list *portlist;
173 struct lcr_msg *message;
176 /* message to test call */
177 admin_call_response(e_adminid, ADMIN_CALL_RELEASE, "", joincause, joinlocation, 0);
179 /* if a release is pending */
180 if (release==RELEASE_JOIN || release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY) {
181 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): do pending release (joincause %d location %d)\n", ea_endpoint->ep_serial, joincause, joinlocation);
182 if (ea_endpoint->ep_join_id) {
183 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_RELEASE);
184 message->param.disconnectinfo.cause = joincause;
185 message->param.disconnectinfo.location = joinlocation;
186 message_put(message);
187 ea_endpoint->ep_join_id = 0;
191 if (release != RELEASE_PORT_JOINONLY) {
193 join_release(e_hold_id, ea_endpoint->ep_serial, 1, joinlocation, joincause);
198 if (release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY) {
199 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release (portcause %d portlocation)\n", ea_endpoint->ep_serial, portcause, portlocation);
200 while((portlist = ea_endpoint->ep_portlist)) {
201 if (portlist->port_id) {
202 SPRINT(cause, "cause_%02x", portcause);
203 set_tone(portlist, cause);
204 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
205 message->param.disconnectinfo.cause = portcause;
206 message->param.disconnectinfo.location = portlocation;
207 message_put(message);
208 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
210 ea_endpoint->free_portlist(portlist);
213 /* if callback is enabled, call back with the given caller id */
215 /* reset some stuff */
216 new_state(EPOINT_STATE_IDLE);
217 memset(&e_connectinfo, 0, sizeof(struct connect_info));
218 memset(&e_redirinfo, 0, sizeof(struct redir_info));
219 e_start = e_stop = 0;
220 e_ruleset = ruleset_main;
222 e_rule = e_ruleset->rule_first;
224 e_action_timeout = 0;
226 e_match_to_action = NULL;
228 e_extdialing = e_dialinginfo.id;
236 e_multipoint_cause = 0;
237 e_multipoint_location = 0;
238 e_dialing_queue[0] = '\0';
240 e_crypt_state = CM_ST_NULL;
241 e_crypt_keyengine_busy = 0;
242 e_crypt_info[0] = '\0';
246 e_tx_state = NOTIFY_STATE_ACTIVE;
247 e_rx_state = NOTIFY_STATE_ACTIVE;
248 e_join_cause = e_join_location = 0;
250 /* the caller info of the callback user */
251 memcpy(&e_callbackinfo, &e_callerinfo, sizeof(e_callbackinfo));
252 memset(&e_dialinginfo, 0, sizeof(e_dialinginfo));
253 /* create dialing by callerinfo */
254 if (e_ext.number[0] && e_extension_interface[0]) {
255 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to internal: %s interface %s\n", ea_endpoint->ep_serial, e_ext.number, e_extension_interface);
256 /* create callback to the current terminal */
257 SCPY(e_dialinginfo.id, e_ext.number);
258 SCPY(e_dialinginfo.interfaces, e_extension_interface);
259 e_dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
260 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
263 SCPY(e_dialinginfo.id, e_cbto);
265 /* numberrize caller id and use it to dial to the callback */
266 SCPY(e_dialinginfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype, options.national, options.international));
268 e_dialinginfo.itype = INFO_ITYPE_ISDN;
269 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
270 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to external: %s\n", ea_endpoint->ep_serial, e_dialinginfo.id);
275 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release of epoint itself.\n", ea_endpoint->ep_serial);
276 ea_endpoint->ep_use--; /* when e_lock is 0, the endpoint will be deleted */
282 /* cancel callerid if restricted, unless anon-ignore is enabled at extension or port is of type external (so called police gets caller id :)*/
283 void apply_callerid_restriction(struct extension *ext, char *id, int *ntype, int *present, int *screen, char *extension, char *name)
285 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");
287 /* caller id is not restricted, so we do nothing */
288 if (*present != INFO_PRESENT_RESTRICTED)
291 /* only extensions are restricted */
295 /* if we enabled anonymouse ignore */
296 if (ext->anon_ignore)
299 /* else we remove the caller id */
303 *ntype = INFO_NTYPE_UNKNOWN;
305 // *screen = INFO_SCREEN_USER;
306 // maybe we should not make voip address anonymous
309 // maybe it's no fraud to present extension id
311 // extension[0] = '\0';
316 /* used display message to display callerid as available */
317 char *EndpointAppPBX::apply_callerid_display(const char *id, int itype, int ntype, int present, int screen, const char *extension, const char *name)
319 static char display[81];
322 const char *cid = numberrize_callerinfo(id, ntype, options.national, options.international);
324 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");
333 /* NOTE: is caller is is not available for this extesion, it has been removed by apply_callerid_restriction already */
335 /* internal extension's caller id */
336 if (extension[0] && e_ext.display_int) {
338 SCAT(display, extension);
341 if (itype == INFO_ITYPE_VBOX)
342 SCAT(display, "(vbox)");
344 SCAT(display, "(int)");
347 /* external caller id */
348 if (!extension[0] && e_ext.display_ext) {
351 if (present == INFO_PRESENT_RESTRICTED)
352 SCAT(display, "anonymous");
354 SCAT(display, "unknown");
361 /* display if callerid is anonymouse but available due anon-ignore */
362 if (e_ext.display_anon && present==INFO_PRESENT_RESTRICTED) {
364 SCAT(display, "unknown");
367 SCAT(display, " anon");
370 /* display if callerid is anonymouse but available due anon-ignore */
371 if (e_ext.display_fake && screen==INFO_SCREEN_USER && ntype!=INFO_NTYPE_NOTPRESENT) {
374 if (present == INFO_PRESENT_RESTRICTED)
375 SCAT(display, "anonymous");
377 SCAT(display, "unknown");
382 SCAT(display, " fake");
386 if (name[0] && e_ext.display_name) {
387 if (!display[0] && cid[0])
398 * uses the current state to notify activity
400 void EndpointAppPBX::notify_active(void)
402 struct port_list *portlist = ea_endpoint->ep_portlist;
403 struct lcr_msg *message;
407 case NOTIFY_STATE_ACTIVE:
408 /* we are already active, so we don't do anything */
411 case NOTIFY_STATE_SUSPEND:
412 notify = INFO_NOTIFY_USER_RESUMED;
414 set_tone(portlist, NULL);
415 portlist = portlist->next;
417 portlist = ea_endpoint->ep_portlist;
420 case NOTIFY_STATE_HOLD:
421 notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
423 set_tone(portlist, NULL);
424 portlist = portlist->next;
426 portlist = ea_endpoint->ep_portlist;
429 case NOTIFY_STATE_CONFERENCE:
430 notify = INFO_NOTIFY_CONFERENCE_DISCONNECTED;
432 set_tone(portlist, NULL);
433 portlist = portlist->next;
435 portlist = ea_endpoint->ep_portlist;
439 PERROR("unknown e_tx_state = %d\n", e_tx_state);
444 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
445 message->param.notifyinfo.notify = notify;
446 message_put(message);
447 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
448 portlist = portlist->next;
454 * keypad functions during call. one example to use this is to put a call on hold or start a conference
456 void EndpointAppPBX::keypad_function(char digit)
459 /* we must be in a call, in order to send messages to the call */
460 if (e_ext.number[0] == '\0') {
461 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) IGNORING keypad received not from extension.\n", ea_endpoint->ep_serial);
466 /* join conference */
468 if (ea_endpoint->ep_join_id == 0) {
469 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad received during connect but not during a call.\n", ea_endpoint->ep_serial);
472 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join call with call on hold\n", ea_endpoint->ep_serial);
478 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) shared key encryption selected.\n", ea_endpoint->ep_serial);
482 /* crypt key-exchange */
484 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) key exchange encryption selected.\n", ea_endpoint->ep_serial);
490 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) encryption off selected.\n", ea_endpoint->ep_serial);
495 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) unsupported keypad digit '%c'.\n", ea_endpoint->ep_serial, digit);
500 /* set tone pattern for port */
501 void EndpointAppPBX::set_tone(struct port_list *portlist, const char *tone)
503 struct lcr_msg *message;
508 /* store for suspended processes */
512 if (e_join_pattern /* pattern are provided */
513 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_SETUP)
514 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_OVERLAP)
515 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_IN_PROCEEDING)
516 && !(e_ext.own_alerting && e_state == EPOINT_STATE_IN_ALERTING)
517 && !(e_ext.own_cause && e_state == EPOINT_STATE_IN_DISCONNECT)
518 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_SETUP)
519 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_OVERLAP)
520 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_OUT_PROCEEDING)
521 && !(e_ext.own_alerting && e_state == EPOINT_STATE_OUT_ALERTING)
522 && !(e_ext.own_cause && e_state == EPOINT_STATE_OUT_DISCONNECT)
523 && tone[0] && !!strncmp(tone,"crypt_*",6)) {
524 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) tone not provided since patterns are available\n", ea_endpoint->ep_serial);
529 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_TONE);
530 SCPY(message->param.tone.dir, e_ext.tones_dir);
531 SCPY(message->param.tone.name, tone);
532 message_put(message);
533 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
535 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port to notify tone.\n", ea_endpoint->ep_serial);
542 * hunts an mISDNport that is available for an outgoing call
543 * if no ifname was given, any interface that is not an extension
546 struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel)
548 struct interface *interface;
549 struct interface_port *ifport, *ifport_start;
550 struct select_channel *selchannel;
551 struct mISDNport *mISDNport;
553 int there_is_an_external = 0;
555 interface = interface_first;
557 /* first find the given interface or, if not given, one with no extension */
560 if (!there_is_an_external && !(ifname && ifname[0])) {
561 trace_header("CHANNEL SELECTION (no external interface specified)", DIRECTION_NONE);
562 add_trace("info", NULL, "Add 'external' parameter to interface.conf.");
568 /* check for given interface */
569 if (ifname && ifname[0]) {
570 if (!strcasecmp(interface->name, ifname)) {
571 /* found explicit interface */
572 trace_header("CHANNEL SELECTION (found given interface)", DIRECTION_NONE);
573 add_trace("interface", NULL, "%s", ifname);
579 if (interface->external) {
580 there_is_an_external = 1;
581 /* found non extension */
582 trace_header("CHANNEL SELECTION (found external interface)", DIRECTION_NONE);
583 add_trace("interface", NULL, "%s", interface->name);
589 interface = interface->next;
593 /* see if interface has ports */
594 if (!interface->ifport) {
596 trace_header("CHANNEL SELECTION (active ports, skipping)", DIRECTION_NONE);
597 add_trace("interface", NULL, "%s", interface->name);
599 interface = interface->next;
603 /* select port by algorithm */
604 ifport_start = interface->ifport;
606 if (interface->hunt == HUNT_ROUNDROBIN) {
607 while(ifport_start->next && index<interface->hunt_next) {
608 ifport_start = ifport_start->next;
611 trace_header("CHANNEL SELECTION (starting round-robin)", DIRECTION_NONE);
612 add_trace("port", NULL, "%d", ifport_start->portnum);
613 add_trace("position", NULL, "%d", index);
618 ifport = ifport_start;
621 /* see if port is available */
622 if (!ifport->mISDNport) {
623 trace_header("CHANNEL SELECTION (port not available, skipping)", DIRECTION_NONE);
624 add_trace("port", NULL, "%d", ifport->portnum);
625 add_trace("position", NULL, "%d", index);
629 mISDNport = ifport->mISDNport;
631 /* see if port is administratively blocked */
633 trace_header("CHANNEL SELECTION (port blocked by admin, skipping)", DIRECTION_NONE);
634 add_trace("port", NULL, "%d", ifport->portnum);
635 add_trace("position", NULL, "%d", index);
640 /* see if link is up on PTP*/
641 if (mISDNport->l2hold && mISDNport->l2link<1) {
642 trace_header("CHANNEL SELECTION (port's layer 2 is down, skipping)", DIRECTION_NONE);
643 add_trace("port", NULL, "%d", ifport->portnum);
644 add_trace("position", NULL, "%d", index);
649 /* check for channel form selection list */
652 if (mISDNport->ss5) {
654 port = ss5_hunt_line(mISDNport);
656 *channel = port->p_m_b_channel;
657 trace_header("CHANNEL SELECTION (selecting SS5 channel)", DIRECTION_NONE);
658 add_trace("port", NULL, "%d", ifport->portnum);
659 add_trace("position", NULL, "%d", index);
660 add_trace("channel", NULL, "%d", *channel);
666 selchannel = ifport->out_channel;
668 switch(selchannel->channel) {
669 case CHANNEL_FREE: /* free channel */
670 if (mISDNport->b_reserved >= mISDNport->b_num)
671 break; /* all channel in use or reserverd */
674 while(i < mISDNport->b_num) {
675 if (mISDNport->b_port[i] == NULL) {
676 *channel = i+1+(i>=15);
677 trace_header("CHANNEL SELECTION (selecting free channel)", DIRECTION_NONE);
678 add_trace("port", NULL, "%d", ifport->portnum);
679 add_trace("position", NULL, "%d", index);
680 add_trace("channel", NULL, "%d", *channel);
688 trace_header("CHANNEL SELECTION (no channel is 'free')", DIRECTION_NONE);
689 add_trace("port", NULL, "%d", ifport->portnum);
690 add_trace("position", NULL, "%d", index);
694 case CHANNEL_ANY: /* don't ask for channel */
695 if (mISDNport->b_reserved >= mISDNport->b_num) {
696 trace_header("CHANNEL SELECTION (cannot ask for 'any' channel, all reserved)", DIRECTION_NONE);
697 add_trace("port", NULL, "%d", ifport->portnum);
698 add_trace("position", NULL, "%d", index);
699 add_trace("total", NULL, "%d", mISDNport->b_num);
700 add_trace("reserved", NULL, "%d", mISDNport->b_reserved);
702 break; /* all channel in use or reserverd */
704 trace_header("CHANNEL SELECTION (using 'any' channel)", DIRECTION_NONE);
705 add_trace("port", NULL, "%d", ifport->portnum);
706 add_trace("position", NULL, "%d", index);
708 *channel = CHANNEL_ANY;
711 case CHANNEL_NO: /* call waiting */
712 trace_header("CHANNEL SELECTION (using 'no' channel, call-waiting)", DIRECTION_NONE);
713 add_trace("port", NULL, "%d", ifport->portnum);
714 add_trace("position", NULL, "%d", index);
716 *channel = CHANNEL_NO;
720 if (selchannel->channel<1 || selchannel->channel==16) {
721 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
722 add_trace("port", NULL, "%d", ifport->portnum);
723 add_trace("position", NULL, "%d", index);
724 add_trace("channel", NULL, "%d", selchannel->channel);
726 break; /* invalid channels */
728 i = selchannel->channel-1-(selchannel->channel>=17);
729 if (i >= mISDNport->b_num) {
730 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
731 add_trace("port", NULL, "%d", ifport->portnum);
732 add_trace("position", NULL, "%d", index);
733 add_trace("channel", NULL, "%d", selchannel->channel);
734 add_trace("channels", NULL, "%d", mISDNport->b_num);
736 break; /* channel not in port */
738 if (mISDNport->b_port[i] == NULL) {
739 *channel = selchannel->channel;
740 trace_header("CHANNEL SELECTION (selecting given channel)", DIRECTION_NONE);
741 add_trace("port", NULL, "%d", ifport->portnum);
742 add_trace("position", NULL, "%d", index);
743 add_trace("channel", NULL, "%d", *channel);
750 break; /* found channel */
751 selchannel = selchannel->next;
755 /* if channel was found, return mISDNport and channel */
757 /* setting next port to start next time */
758 if (interface->hunt == HUNT_ROUNDROBIN) {
762 interface->hunt_next = index;
768 trace_header("CHANNEL SELECTION (skipping, no channel found)", DIRECTION_NONE);
769 add_trace("port", NULL, "%d", ifport->portnum);
770 add_trace("position", NULL, "%d", index);
774 /* go next port, until all ports are checked */
776 ifport = ifport->next;
779 ifport = interface->ifport;
781 if (ifport != ifport_start)
785 interface = interface->next;
789 return(NULL); /* no port found */
792 /* outgoing setup to port(s)
793 * ports will be created and a setup is sent if everything is ok. otherwhise
794 * the endpoint is destroyed.
796 void EndpointAppPBX::out_setup(void)
798 struct dialing_info dialinginfo;
800 struct port_list *portlist;
801 struct lcr_msg *message;
803 int cause = CAUSE_RESSOURCEUNAVAIL;
806 struct mISDNport *mISDNport;
809 class EndpointAppPBX *atemp;
810 // char allowed_ports[256];
812 char ifname[sizeof(e_ext.interfaces)],
814 struct port_settings port_settings;
817 int mode = B_MODE_TRANSPARENT;
819 /* set bchannel mode */
820 mode = e_capainfo.source_mode;
822 /* create settings for creating port */
823 memset(&port_settings, 0, sizeof(port_settings));
825 SCPY(port_settings.tones_dir, e_ext.tones_dir);
827 SCPY(port_settings.tones_dir, options.tones_dir);
828 port_settings.no_seconds = e_ext.no_seconds;
830 /* 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 */
832 /* check what dialinginfo.itype we got */
833 switch(e_dialinginfo.itype) {
834 /* *********************** call to extension or vbox */
835 case INFO_ITYPE_ISDN_EXTENSION:
836 /* check if we deny incoming calls when we use an extension */
837 if (e_ext.noknocking) {
838 atemp = apppbx_first;
841 if (!strcmp(atemp->e_ext.number, e_ext.number))
846 PERROR("EPOINT(%d) noknocking and currently a call\n", ea_endpoint->ep_serial);
847 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYSPE_ join, port */
848 return; /* must exit here */
851 /* FALL THROUGH !!!! */
852 case INFO_ITYPE_VBOX:
853 /* get dialed extension's info */
854 // SCPY(exten, e_dialinginfo.id);
855 // if (strchr(exten, ','))
856 // *strchr(exten, ',') = '\0';
857 // if (!read_extension(&e_ext, exten))
858 if (!read_extension(&e_ext, e_dialinginfo.id)) {
859 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) extension %s not configured\n", ea_endpoint->ep_serial, e_dialinginfo.id);
860 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
861 return; /* must exit here */
864 if (e_dialinginfo.itype == INFO_ITYPE_VBOX) {
865 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing directly to VBOX\n", ea_endpoint->ep_serial);
870 /* string from unconditional call forward (cfu) */
873 /* present to forwarded party */
874 if (e_ext.anon_ignore && e_callerinfo.id[0]) {
875 e_callerinfo.present = INFO_PRESENT_ALLOWED;
877 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
881 /* string from busy call forward (cfb) */
884 class EndpointAppPBX *checkapp = apppbx_first;
886 if (checkapp != this) { /* any other endpoint except our own */
887 if (!strcmp(checkapp->e_ext.number, e_ext.number)) {
888 /* present to forwarded party */
889 if (e_ext.anon_ignore && e_callerinfo.id[0]) {
890 e_callerinfo.present = INFO_PRESENT_ALLOWED;
892 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
896 checkapp = checkapp->next;
900 /* string from no-response call forward (cfnr) */
903 /* when cfnr is done, out_setup() will setup the call */
905 /* present to forwarded party */
906 if (e_ext.anon_ignore && e_callerinfo.id[0]) {
907 e_callerinfo.present = INFO_PRESENT_ALLOWED;
911 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH)) {
912 e_cfnr_release = now + e_ext.cfnr_delay;
913 e_cfnr_call = now + e_ext.cfnr_delay + 1; /* call one second after release */
914 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);
918 /* call to all internal interfaces */
919 p = e_ext.interfaces;
920 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) generating multiple joins for extension %s to interfaces %s\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
923 while(*p!=',' && *p!='\0')
928 /* found interface */
929 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
930 /* hunt for mISDNport and create Port */
931 mISDNport = hunt_port(ifname, &channel);
933 trace_header("INTERFACE (not found or busy)", DIRECTION_NONE);
934 add_trace("interface", NULL, "%s", ifname);
938 /* creating INTERNAL port */
939 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
942 port = ss5_hunt_line(mISDNport);
946 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);
949 port = new Pgsm(PORT_TYPE_GSM_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
954 FATAL("No memory for Port instance\n");
955 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
956 memset(&dialinginfo, 0, sizeof(dialinginfo));
957 SCPY(dialinginfo.id, e_dialinginfo.id);
958 dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
959 dialinginfo.ntype = e_dialinginfo.ntype;
960 /* create port_list relation */
961 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
963 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
965 goto check_anycall_intern;
968 if (e_callerinfo.id[0] && e_ext.display_name) {
969 dirname = parse_directory(e_callerinfo.id, e_callerinfo.ntype);
971 SCPY(e_callerinfo.name, dirname);
973 // dss1 = (class Pdss1 *)port;
975 //printf("INTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
976 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
977 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
978 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
979 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
980 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
981 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
982 //terminal if (e_dialinginfo.id)
983 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
984 /* handle restricted caller ids */
985 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);
986 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);
987 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);
988 /* display callerid if desired for extension */
989 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));
990 //printf("\n\ndisplay = %s\n\n\n",message->param.setup.callerinfo.display);
991 /* use cnip, if enabld */
992 // if (!e_ext.centrex)
993 // message->param.setup.callerinfo.name[0] = '\0';
994 /* screen clip if prefix is required */
995 if (message->param.setup.callerinfo.id[0] && e_ext.clip_prefix[0]) {
996 SCPY(message->param.setup.callerinfo.id, e_ext.clip_prefix);
997 SCAT(message->param.setup.callerinfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype, options.national, options.international));
998 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1000 if (message->param.setup.callerinfo.id2[0] && e_ext.clip_prefix[0]) {
1001 SCPY(message->param.setup.callerinfo.id2, e_ext.clip_prefix);
1002 SCAT(message->param.setup.callerinfo.id2, numberrize_callerinfo(e_callerinfo.id2,e_callerinfo.ntype2, options.national, options.international));
1003 message->param.setup.callerinfo.ntype2 = INFO_NTYPE_UNKNOWN;
1005 /* use internal caller id */
1006 if (e_callerinfo.extension[0] && (message->param.setup.callerinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore)) {
1007 SCPY(message->param.setup.callerinfo.id, e_callerinfo.extension);
1008 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1009 message->param.setup.callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
1011 message_put(message);
1012 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1016 /* string from parallel call forward (cfp) */
1019 if (e_ext.anon_ignore && e_callerinfo.id[0]) {
1020 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1021 e_callerinfo.present2 = INFO_PRESENT_ALLOWED;
1025 vbox_only: /* entry point for answering machine only */
1026 cfu_only: /* entry point for cfu */
1027 cfb_only: /* entry point for cfb */
1028 cfnr_only: /* entry point for cfnr */
1029 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call extension %s for external destiantion(s) '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
1033 /* only if vbox should be dialed, and terminal is given */
1034 if (!strcmp(p, "vbox") && e_ext.number[0]) {
1035 /* go to the end of p */
1038 /* answering vbox call */
1039 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) answering machine\n", ea_endpoint->ep_serial);
1041 if (!(port = new VBoxPort(PORT_TYPE_VBOX_OUT, &port_settings)))
1042 FATAL("No memory for VBOX Port instance\n");
1043 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocated port %s\n", ea_endpoint->ep_serial, port->p_name);
1044 UCPY(cfp, e_ext.number); /* cfp or any other direct forward/vbox */
1047 while(*p!=',' && *p!='\0')
1052 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cfp external %s\n", ea_endpoint->ep_serial, cfp);
1053 /* hunt for mISDNport and create Port */
1054 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1056 /* creating EXTERNAL port*/
1057 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1060 port = ss5_hunt_line(mISDNport);
1063 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);
1065 FATAL("No memory for Port instance\n");
1066 earlyb = mISDNport->earlyb;
1069 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1070 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1075 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port found or created, which is idle.\n", ea_endpoint->ep_serial);
1076 goto check_anycall_intern;
1078 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found or created port %s\n", ea_endpoint->ep_serial, port->p_name);
1079 memset(&dialinginfo, 0, sizeof(dialinginfo));
1080 SCPY(dialinginfo.id, cfp);
1081 dialinginfo.itype = INFO_ITYPE_ISDN;
1082 dialinginfo.ntype = e_dialinginfo.ntype;
1083 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
1085 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1087 goto check_anycall_intern;
1089 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1090 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1091 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1092 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1093 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1094 /* if clip is hidden */
1095 if (e_ext.clip==CLIP_HIDE && port->p_type!=PORT_TYPE_VBOX_OUT) {
1096 SCPY(message->param.setup.callerinfo.id, e_ext.callerid);
1097 SCPY(message->param.setup.callerinfo.extension, e_ext.number);
1098 message->param.setup.callerinfo.ntype = e_ext.callerid_type;
1099 message->param.setup.callerinfo.present = e_ext.callerid_present;
1100 message->param.setup.callerinfo.ntype = INFO_NTYPE_NOTPRESENT;
1102 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1103 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1104 //terminal if (e_dialinginfo.id)
1105 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1106 /* handle restricted caller ids */
1107 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);
1108 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);
1109 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);
1110 /* display callerid if desired for extension */
1111 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));
1112 message_put(message);
1113 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1117 check_anycall_intern:
1118 /* now we have all ports created */
1120 trace_header("INTERFACE (no extension's interface)", DIRECTION_NONE);
1122 if (!ea_endpoint->ep_join_id)
1124 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1125 return; /* must exit here */
1129 /* *********************** external call */
1131 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id);
1132 /* call to extenal interfaces */
1133 p = e_dialinginfo.id;
1136 while(*p!=',' && *p!='\0')
1137 SCCAT(number, *p++);
1141 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");
1142 /* hunt for mISDNport and create Port */
1143 /* hunt for mISDNport and create Port */
1144 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1146 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1147 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1149 goto check_anycall_extern;
1151 /* creating EXTERNAL port*/
1152 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1155 port = ss5_hunt_line(mISDNport);
1158 if (!mISDNport->gsm)
1159 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);
1162 port = new Pgsm(PORT_TYPE_GSM_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
1167 FATAL("No memory for Port instance\n");
1168 earlyb = mISDNport->earlyb;
1169 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
1170 memset(&dialinginfo, 0, sizeof(dialinginfo));
1171 SCPY(dialinginfo.id, number);
1172 dialinginfo.itype = INFO_ITYPE_ISDN;
1173 dialinginfo.ntype = e_dialinginfo.ntype;
1174 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
1176 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1178 goto check_anycall_extern;
1180 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1181 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1182 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1183 SCPY(message->param.setup.dialinginfo.id, number);
1184 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1185 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1186 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1187 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1188 //terminal if (e_dialinginfo.id)
1189 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1190 /* handle restricted caller ids */
1191 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);
1192 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);
1193 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);
1194 /* display callerid if desired for extension */
1195 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));
1196 message_put(message);
1197 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1201 check_anycall_extern:
1202 /* now we have all ports created */
1204 trace_header("INTERFACE (no free ports found)", DIRECTION_NONE);
1206 if (!ea_endpoint->ep_join_id)
1208 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1209 return; /* must exit here */
1217 /* handler for endpoint
1221 int EndpointAppPBX::handler(void)
1223 if (e_crypt_state!=CM_ST_NULL) {
1227 /* process answering machine (play) handling */
1229 if (e_action->index == ACTION_VBOX_PLAY)
1232 /* process action timeout */
1233 if (e_action_timeout)
1234 if (now_d >= e_action_timeout) {
1235 if (e_state!=EPOINT_STATE_CONNECT) {
1237 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current action timed out.\n", ea_endpoint->ep_serial);
1238 e_multipoint_cause = 0;
1239 e_multipoint_location = 0;
1240 new_state(EPOINT_STATE_IN_OVERLAP);
1243 return(1); /* we must exit, because our endpoint might be gone */
1245 e_action_timeout = 0;
1248 /* process action timeout */
1249 if (e_match_timeout)
1250 if (now_d >= e_match_timeout) {
1252 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we got a match timeout.\n", ea_endpoint->ep_serial);
1254 return(1); /* we must exit, because our endpoint might be gone */
1259 /* process redialing (epoint redials to port) */
1261 if (now_d >= e_redial) {
1263 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial.\n", ea_endpoint->ep_serial);
1265 new_state(EPOINT_STATE_OUT_SETUP);
1266 /* call special setup routine */
1273 /* process powerdialing (epoint redials to epoint) */
1274 if (e_powerdialing > 0) {
1275 if (now_d >= e_powerdialing) {
1276 e_powerdialing = -1; /* leave power dialing on */
1277 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial of powerdial.\n", ea_endpoint->ep_serial);
1280 e_ruleset = ruleset_main;
1282 e_rule = e_ruleset->rule_first;
1284 new_state(EPOINT_STATE_IN_OVERLAP);
1290 /* process call forward no response */
1291 if (e_cfnr_release) {
1292 struct port_list *portlist;
1293 struct lcr_msg *message;
1295 if (now >= e_cfnr_release) {
1296 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-no-response time has expired, hanging up.\n", ea_endpoint->ep_serial);
1299 /* release all ports */
1300 while((portlist = ea_endpoint->ep_portlist)) {
1301 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1302 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
1303 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1304 message_put(message);
1305 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1306 ea_endpoint->free_portlist(portlist);
1309 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1310 message->param.audiopath = 0;
1311 message_put(message);
1312 /* indicate no patterns */
1313 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1314 message_put(message);
1315 /* set setup state, since we have no response from the new join */
1316 new_state(EPOINT_STATE_OUT_SETUP);
1320 if (now >= e_cfnr_call) {
1321 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-busy time has expired, calling the forwarded number: %s.\n", ea_endpoint->ep_serial, e_ext.cfnr);
1327 /* handle connection to user */
1328 if (e_state == EPOINT_STATE_IDLE) {
1329 /* epoint is idle, check callback */
1331 if (now_d >= e_callback) {
1332 e_callback = 0; /* done with callback */
1333 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting callback.\n", ea_endpoint->ep_serial);
1334 new_state(EPOINT_STATE_OUT_SETUP);
1340 /* check for password timeout */
1342 if (e_action->index==ACTION_PASSWORD || e_action->index==ACTION_PASSWORD_WRITE) {
1343 struct port_list *portlist;
1345 if (now >= e_password_timeout) {
1346 e_ruleset = ruleset_main;
1348 e_rule = e_ruleset->rule_first;
1350 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) password timeout %s\n", ea_endpoint->ep_serial, e_extdialing);
1351 trace_header("PASSWORD timeout", DIRECTION_NONE);
1353 e_connectedmode = 0;
1355 new_state(EPOINT_STATE_OUT_DISCONNECT);
1356 portlist = ea_endpoint->ep_portlist;
1358 message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
1359 set_tone(portlist, "cause_10");
1369 /* doing a hookflash */
1370 void EndpointAppPBX::hookflash(void)
1374 /* be sure that we are active */
1376 e_tx_state = NOTIFY_STATE_ACTIVE;
1378 trace_header("HOOKFLASH DTMF", DIRECTION_NONE);
1380 if (ea_endpoint->ep_use > 1) {
1381 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot hooflash while child process is running.\n", ea_endpoint->ep_serial);
1384 /* dialtone after pressing the hash key */
1385 process_hangup(e_join_cause, e_join_location);
1386 e_multipoint_cause = 0;
1387 e_multipoint_location = 0;
1388 port = find_port_id(ea_endpoint->ep_portlist->port_id);
1390 port->set_echotest(0);
1392 if (ea_endpoint->ep_join_id) {
1393 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1395 e_ruleset = ruleset_main;
1397 e_rule = e_ruleset->rule_first;
1399 new_state(EPOINT_STATE_IN_OVERLAP);
1400 e_connectedmode = 1;
1401 SCPY(e_dialinginfo.id, e_ext.prefix);
1402 e_extdialing = e_dialinginfo.id;
1404 if (e_dialinginfo.id[0]) {
1405 set_tone(ea_endpoint->ep_portlist, "dialing");
1408 set_tone(ea_endpoint->ep_portlist, "dialpbx");
1415 /* messages from port
1417 /* port MESSAGE_SETUP */
1418 void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, union parameter *param)
1420 struct lcr_msg *message;
1422 int writeext; /* flags need to write extension after modification */
1424 struct interface *interface;
1426 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1428 portlist->port_type = param->setup.port_type;
1429 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
1430 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
1431 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
1432 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
1433 // e_dtmf = param->setup.dtmf;
1434 /* screen incoming caller id */
1435 interface = interface_first;
1437 if (!strcmp(e_callerinfo.interface, interface->name)) {
1440 interface = interface->next;
1443 do_screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface);
1444 do_screen(0, e_callerinfo.id2, sizeof(e_callerinfo.id2), &e_callerinfo.ntype2, &e_callerinfo.present2, interface);
1447 /* process extension */
1448 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION) {
1449 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is extension\n", ea_endpoint->ep_serial);
1450 /* port makes call from extension */
1451 SCPY(e_callerinfo.extension, e_callerinfo.id);
1452 SCPY(e_ext.number, e_callerinfo.extension);
1453 SCPY(e_extension_interface, e_callerinfo.interface);
1455 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is external or voip\n", ea_endpoint->ep_serial);
1458 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION) {
1459 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1461 /* get extension's info about caller */
1462 if (!read_extension(&e_ext, e_ext.number)) {
1463 /* extension doesn't exist */
1464 trace_header("EXTENSION (not created)", DIRECTION_IN);
1465 add_trace("extension", NULL, "%s", e_ext.number);
1467 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
1468 new_state(EPOINT_STATE_OUT_DISCONNECT);
1469 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
1470 e_ext.number[0] = '\0'; /* no terminal */
1475 /* put prefix (next) in front of e_dialinginfo.id */
1476 if (e_ext.next[0]) {
1477 SPRINT(buffer, "%s%s", e_ext.next, e_dialinginfo.id);
1478 SCPY(e_dialinginfo.id, buffer);
1479 e_ext.next[0] = '\0';
1481 } else if (e_ext.prefix[0]) {
1482 SPRINT(buffer, "%s%s", e_ext.prefix, e_dialinginfo.id);
1483 SCPY(e_dialinginfo.id, buffer);
1486 /* screen caller id by extension's config */
1487 e_callerinfo.screen = INFO_SCREEN_NETWORK;
1489 SCPY(e_callerinfo.name, e_ext.name);
1490 /* use caller id (or if exist: id_next_call) for this call */
1491 if (e_ext.id_next_call_present >= 0) {
1492 SCPY(e_callerinfo.id, e_ext.id_next_call);
1493 /* if we restrict the pesentation */
1494 if (e_ext.id_next_call_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1495 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1496 else e_callerinfo.present = e_ext.id_next_call_present;
1497 e_callerinfo.ntype = e_ext.id_next_call_type;
1498 e_ext.id_next_call_present = -1;
1501 SCPY(e_callerinfo.id, e_ext.callerid);
1502 /* if we restrict the pesentation */
1503 if (e_ext.callerid_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1504 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1505 else e_callerinfo.present = e_ext.callerid_present;
1506 e_callerinfo.ntype = e_ext.callerid_type;
1508 e_callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
1510 /* extension is written */
1512 write_extension(&e_ext, e_ext.number);
1514 /* set volume of rx and tx */
1515 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1516 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0) {
1517 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
1518 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
1519 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
1520 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
1521 message_put(message);
1524 /* start recording if enabled */
1525 if (e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO)) {
1526 /* check if we are a terminal */
1527 if (e_ext.number[0] == '\0')
1528 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
1530 port = find_port_id(portlist->port_id);
1532 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
1536 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from external port\n", ea_endpoint->ep_serial);
1537 /* no terminal identification */
1538 e_ext.number[0] = '\0';
1539 e_extension_interface[0] = '\0';
1540 memset(&e_ext, 0, sizeof(e_ext));
1541 e_ext.rights = 4; /* right to dial internat */
1545 e_ruleset = ruleset_main;
1547 e_rule = e_ruleset->rule_first;
1549 e_extdialing = e_dialinginfo.id;
1550 new_state(EPOINT_STATE_IN_SETUP);
1551 if (e_dialinginfo.id[0]) {
1552 set_tone(portlist, "dialing");
1554 if (e_ext.number[0])
1555 set_tone(portlist, "dialpbx");
1557 set_tone(portlist, "dialtone");
1560 if (e_state == EPOINT_STATE_IN_SETUP) {
1561 /* request MORE info, if not already at higher state */
1562 new_state(EPOINT_STATE_IN_OVERLAP);
1563 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_OVERLAP);
1564 message_put(message);
1565 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1569 /* port MESSAGE_INFORMATION */
1570 void EndpointAppPBX::port_information(struct port_list *portlist, int message_type, union parameter *param)
1572 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1574 /* ignore information message without digit information */
1575 if (!param->information.id[0])
1580 /* turn off dtmf detection, in case dtmf is sent with keypad information */
1582 trace_header("DTMF (disabling due to keypad)", DIRECTION_IN);
1587 /* if vbox_play is done, the information are just used as they come */
1589 if (e_action->index == ACTION_VBOX_PLAY) {
1590 /* concat dialing string */
1591 SCAT(e_dialinginfo.id, param->information.id);
1596 /* keypad when disconnect but in connected mode */
1597 if (e_state==EPOINT_STATE_OUT_DISCONNECT && e_connectedmode) {
1598 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received after disconnect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1599 /* processing keypad function */
1600 if (param->information.id[0] == '0') {
1606 /* keypad when connected */
1607 if (e_state == EPOINT_STATE_CONNECT || e_state == EPOINT_STATE_IN_ALERTING) {
1608 if (e_ext.keypad || e_enablekeypad) {
1609 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1610 /* processing keypad function */
1611 if (param->information.id[0] == '0') {
1614 if (param->information.id[0])
1615 keypad_function(param->information.id[0]);
1617 if (e_ext.number[0])
1618 trace_header("KEYPAD (not enabled by extension's settings)", DIRECTION_IN);
1620 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1625 if (e_state != EPOINT_STATE_IN_OVERLAP) {
1626 if (e_ext.number[0])
1627 trace_header("KEYPAD (ignored, not connected and not dialing)", DIRECTION_IN);
1629 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1633 if (!param->information.id[0])
1635 if (e_dialinginfo.id[0]=='\0' && !e_action) {
1636 set_tone(portlist, "dialing");
1639 if (e_action->index==ACTION_OUTDIAL
1640 || e_action->index==ACTION_EXTERNAL
1641 || e_action->index==ACTION_REMOTE) {
1643 set_tone(portlist, "dialing");
1644 else if (!e_extdialing[0])
1645 set_tone(portlist, "dialing");
1647 /* concat dialing string */
1648 SCAT(e_dialinginfo.id, param->information.id);
1652 /* port MESSAGE_DTMF */
1653 void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
1655 /* only if dtmf detection is enabled */
1657 trace_header("DTMF (disabled)", DIRECTION_IN);
1661 trace_header("DTMF", DIRECTION_IN);
1662 add_trace("digit", NULL, "%c", param->dtmf);
1666 NOTE: vbox is now handled due to overlap state
1667 /* if vbox_play is done, the dtmf digits are just used as they come */
1669 if (e_action->index == ACTION_VBOX_PLAY) {
1670 /* concat dialing string */
1671 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id)) {
1672 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1673 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1676 /* continue to process *X# sequences */
1680 /* check for *X# sequence */
1681 if (e_state == EPOINT_STATE_CONNECT || e_state == EPOINT_STATE_IN_ALERTING) {
1682 if (e_dtmf_time+3 < now) {
1683 /* the last digit was too far in the past to be a sequence */
1684 if (param->dtmf == '*')
1685 /* only start is allowed in the sequence */
1690 /* we have a sequence of digits, see what we got */
1691 if (param->dtmf == '*')
1693 else if (param->dtmf>='0' && param->dtmf<='9') {
1694 /* we need to have a star before we receive the digit of the sequence */
1695 if (e_dtmf_last == '*')
1696 e_dtmf_last = param->dtmf;
1697 } else if (param->dtmf == '#') {
1699 if (e_dtmf_last>='0' && e_dtmf_last<='9') {
1700 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf sequence *%c# detected.\n", ea_endpoint->ep_serial, e_dtmf_last);
1701 if (e_dtmf_last == '0') {
1705 /* processing keypad function */
1707 keypad_function(e_dtmf_last);
1713 /* set last time of dtmf */
1718 /* check for ## hookflash during dialing */
1720 if (e_action->index==ACTION_PASSWORD
1721 || e_action->index==ACTION_PASSWORD_WRITE)
1723 if (param->dtmf=='#') { /* current digit is '#' */
1724 if (e_state==EPOINT_STATE_IN_DISCONNECT
1725 || (e_state!=EPOINT_STATE_CONNECT && e_dtmf_time+3>=now && e_dtmf_last=='#')) { /* when disconnected, just #. when dialing, ##. */
1739 /* dialing using dtmf digit */
1740 if (e_state==EPOINT_STATE_IN_OVERLAP){ // && e_state==e_connectedmode)
1741 if (e_dialinginfo.id[0]=='\0' && !e_action) {
1742 set_tone(portlist, "dialing");
1744 /* concat dialing string */
1745 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id)) {
1746 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1747 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1753 /* port MESSAGE_CRYPT */
1754 void EndpointAppPBX::port_crypt(struct port_list *portlist, int message_type, union parameter *param)
1756 /* send crypt response to cryptman */
1757 if (param->crypt.type == CR_MESSAGE_IND)
1758 cryptman_msg2man(param->crypt.data, param->crypt.len);
1760 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
1763 /* port MESSAGE_OVERLAP */
1764 void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, union parameter *param)
1766 struct lcr_msg *message;
1768 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1770 /* signal to call tool */
1771 admin_call_response(e_adminid, ADMIN_CALL_SETUP_ACK, "", 0, 0, 0);
1773 if (e_dialing_queue[0] && portlist) {
1774 /* send what we have not dialed yet, because we had no setup complete */
1775 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing pending digits: '%s'\n", ea_endpoint->ep_serial, e_dialing_queue);
1776 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
1777 SCPY(message->param.information.id, e_dialing_queue);
1778 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
1779 message_put(message);
1780 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
1781 e_dialing_queue[0] = '\0';
1783 /* check if pattern is available */
1784 if (!ea_endpoint->ep_portlist->next && portlist->early_b) { /* one port_list relation and tones available */
1785 /* indicate patterns */
1786 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1787 message_put(message);
1789 /* connect audio, if not already */
1790 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1791 message->param.audiopath = 1;
1792 message_put(message);
1794 /* indicate no patterns */
1795 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1796 message_put(message);
1798 /* disconnect audio, if not already */
1799 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1800 message->param.audiopath = 0;
1801 message_put(message);
1803 new_state(EPOINT_STATE_OUT_OVERLAP);
1804 /* if we are in a join */
1805 if (ea_endpoint->ep_join_id) {
1806 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1807 memcpy(&message->param, param, sizeof(union parameter));
1808 message_put(message);
1812 /* port MESSAGE_PROCEEDING */
1813 void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_type, union parameter *param)
1815 struct lcr_msg *message;
1817 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1819 /* signal to call tool */
1820 admin_call_response(e_adminid, ADMIN_CALL_PROCEEDING, "", 0, 0, 0);
1822 e_state = EPOINT_STATE_OUT_PROCEEDING;
1823 /* check if pattern is availatle */
1824 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) { /* one port_list relation and tones available */
1825 /* indicate patterns */
1826 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1827 message_put(message);
1829 /* connect audio, if not already */
1830 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1831 message->param.audiopath = 1;
1832 message_put(message);
1834 /* indicate no patterns */
1835 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1836 message_put(message);
1838 /* disconnect audio, if not already */
1839 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1840 message->param.audiopath = 0;
1841 message_put(message);
1843 /* if we are in a call */
1844 if (ea_endpoint->ep_join_id) {
1845 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1846 memcpy(&message->param, param, sizeof(union parameter));
1847 message_put(message);
1851 /* port MESSAGE_ALERTING */
1852 void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type, union parameter *param)
1854 struct lcr_msg *message;
1856 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1858 /* signal to call tool */
1859 admin_call_response(e_adminid, ADMIN_CALL_ALERTING, "", 0, 0, 0);
1862 // set_tone(portlist, "hold");
1864 new_state(EPOINT_STATE_OUT_ALERTING);
1865 /* check if pattern is available */
1866 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) { /* one port_list relation and tones available */
1867 /* indicate patterns */
1868 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1869 message_put(message);
1871 /* connect audio, if not already */
1872 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1873 message->param.audiopath = 1;
1874 message_put(message);
1876 /* indicate no patterns */
1877 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1878 message_put(message);
1880 /* disconnect audio, if not already */
1881 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1882 message->param.audiopath = 0;
1883 message_put(message);
1885 /* if we are in a call */
1886 if (ea_endpoint->ep_join_id) {
1887 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1888 memcpy(&message->param, param, sizeof(union parameter));
1889 message_put(message);
1893 /* port MESSAGE_CONNECT */
1894 void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, union parameter *param)
1896 struct lcr_msg *message;
1898 unsigned int port_id = portlist->port_id;
1899 struct port_list *tportlist;
1901 struct interface *interface;
1903 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1905 /* signal to call tool */
1906 admin_call_response(e_adminid, ADMIN_CALL_CONNECT, numberrize_callerinfo(param->connectinfo.id,param->connectinfo.ntype, options.national, options.international), 0, 0, 0);
1908 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_connectinfo));
1909 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (start)\n", ea_endpoint->ep_serial);
1910 while(ea_endpoint->ep_portlist->next) { /* as long as we have at least two ports */
1911 tportlist = ea_endpoint->ep_portlist;
1912 if (tportlist->port_id == port_id) /* if the first portlist is the calling one, the second must be a different one */
1913 tportlist = tportlist->next;
1914 if (tportlist->port_id == port_id)
1915 FATAL("EPOINT(%d) this should not happen since the portlist list must not have two links to the same port - exitting.\n");
1916 message = message_create(ea_endpoint->ep_serial, tportlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1917 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
1918 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1919 message_put(message);
1920 logmessage(message->type, &message->param, tportlist->port_id, DIRECTION_OUT);
1921 ea_endpoint->free_portlist(tportlist);
1923 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (end)\n", ea_endpoint->ep_serial);
1927 /* screen incoming connected id */
1928 interface = interface_first;
1930 if (!strcmp(e_connectinfo.interface, interface->name)) {
1933 interface = interface->next;
1936 do_screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface);
1938 /* screen connected name */
1940 SCPY(e_connectinfo.name, e_ext.name);
1942 /* add internal id to colp */
1943 SCPY(e_connectinfo.extension, e_ext.number);
1945 /* we store the connected port number */
1946 SCPY(e_extension_interface, e_connectinfo.interface);
1948 /* for internal and am calls, we get the extension's id */
1949 if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE) {
1950 SCPY(e_connectinfo.id, e_ext.callerid);
1951 SCPY(e_connectinfo.extension, e_ext.number);
1952 e_connectinfo.itype = INFO_ITYPE_ISDN_EXTENSION;
1953 e_connectinfo.ntype = e_ext.callerid_type;
1954 e_connectinfo.present = e_ext.callerid_present;
1956 if (portlist->port_type==PORT_TYPE_VBOX_OUT) {
1957 e_connectinfo.itype = INFO_ITYPE_VBOX;
1958 e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
1961 new_state(EPOINT_STATE_CONNECT);
1963 /* set volume of rx and tx */
1964 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0) {
1965 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
1966 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
1967 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
1968 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
1969 message_put(message);
1972 e_cfnr_call = e_cfnr_release = 0;
1973 if (e_ext.number[0])
1974 e_dtmf = 1; /* allow dtmf */
1977 /* other calls with no caller id (or not available for the extension) and force colp */
1978 if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE) {
1979 e_connectinfo.ntype = INFO_NTYPE_NOTPRESENT;
1980 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 */
1981 port = find_port_id(portlist->port_id);
1983 SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.id, &e_connectinfo.ntype, options.national, options.international));
1984 e_connectinfo.present = INFO_PRESENT_ALLOWED;
1989 /* send connect to join */
1990 if (ea_endpoint->ep_join_id) {
1991 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1992 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
1993 message_put(message);
1995 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1996 message->param.audiopath = 1;
1997 message_put(message);
1998 } else if (!e_adminid) {
2000 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have a callback, so we create a call with cbcaller: \"%s\".\n", ea_endpoint->ep_serial, e_cbcaller);
2001 SCPY(e_ext.number, e_cbcaller);
2002 new_state(EPOINT_STATE_IN_OVERLAP);
2003 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) callback from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2005 /* get extension's info about terminal */
2006 if (!read_extension(&e_ext, e_ext.number)) {
2007 /* extension doesn't exist */
2008 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2009 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
2010 new_state(EPOINT_STATE_OUT_DISCONNECT);
2011 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
2015 /* put prefix in front of e_cbdialing */
2016 SPRINT(buffer, "%s%s", e_ext.prefix, e_cbdialing);
2017 SCPY(e_dialinginfo.id, buffer);
2018 e_dialinginfo.itype = INFO_ITYPE_ISDN;
2019 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
2021 /* use caller id (or if exist: id_next_call) for this call */
2022 e_callerinfo.screen = INFO_SCREEN_NETWORK;
2023 SCPY(e_callerinfo.extension, e_ext.number);
2024 if (e_ext.id_next_call_present >= 0) {
2025 SCPY(e_callerinfo.id, e_ext.id_next_call);
2026 e_callerinfo.present = e_ext.id_next_call_present;
2027 e_callerinfo.ntype = e_ext.id_next_call_type;
2028 e_ext.id_next_call_present = -1;
2029 /* extension is written */
2030 write_extension(&e_ext, e_ext.number);
2032 SCPY(e_callerinfo.id, e_ext.callerid);
2033 e_callerinfo.present = e_ext.callerid_present;
2034 e_callerinfo.ntype = e_ext.callerid_type;
2036 e_callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
2038 e_connectedmode = 1; /* dtmf-hangup & disconnect prevention */
2041 /* check if caller id is NOT authenticated */
2042 if (!parse_callbackauth(e_ext.number, &e_callbackinfo)) {
2043 /* make call state to enter password */
2044 new_state(EPOINT_STATE_IN_OVERLAP);
2045 e_action = &action_password_write;
2046 e_match_timeout = 0;
2047 e_match_to_action = NULL;
2048 e_dialinginfo.id[0] = '\0';
2049 e_extdialing = strchr(e_dialinginfo.id, '\0');
2050 e_password_timeout = now+20;
2053 /* incoming call (callback) */
2054 e_ruleset = ruleset_main;
2056 e_rule = e_ruleset->rule_first;
2058 e_extdialing = e_dialinginfo.id;
2059 if (e_dialinginfo.id[0]) {
2060 set_tone(portlist, "dialing");
2063 set_tone(portlist, "dialpbx");
2066 } else { /* testcall */
2067 set_tone(portlist, "hold");
2070 /* start recording if enabled, not when answering machine answers */
2071 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)) {
2072 /* check if we are a terminal */
2073 if (e_ext.number[0] == '\0')
2074 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
2076 port = find_port_id(portlist->port_id);
2078 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
2083 /* port MESSAGE_DISCONNECT MESSAGE_RELEASE */
2084 void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
2086 struct lcr_msg *message;
2088 unsigned int port_id = portlist->port_id;
2092 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2094 /* signal to call tool */
2095 admin_call_response(e_adminid, (message_type==MESSAGE_DISCONNECT)?ADMIN_CALL_DISCONNECT:ADMIN_CALL_RELEASE, "", param->disconnectinfo.cause, param->disconnectinfo.location, 0);
2097 //#warning does this work? only disconnect when incoming port hat not already disconnected yet?
2098 if (e_state==EPOINT_STATE_IN_DISCONNECT && message_type!=MESSAGE_RELEASE){ // || e_state==EPOINT_STATE_OUT_DISCONNECT || e_state==EPOINT_STATE_IDLE)
2099 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are already disconnected.\n", ea_endpoint->ep_serial);
2104 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);
2105 collect_cause(&e_multipoint_cause, &e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location);
2106 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new multipoint cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location);
2108 /* check if we have more than one portlist relation and we just ignore the disconnect */
2109 if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist->next) {
2110 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the disconnect was from a multipoint call. we just release that relation.\n", ea_endpoint->ep_serial);
2111 portlist = ea_endpoint->ep_portlist;
2113 if (portlist->port_id == port_id)
2115 portlist = portlist->next;
2118 FATAL("EPOINT(%d) no portlist related to the calling port.\n", ea_endpoint->ep_serial);
2119 if (message_type != MESSAGE_RELEASE) {
2120 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2121 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2122 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2123 message_put(message);
2124 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2126 ea_endpoint->free_portlist(portlist);
2127 return; /* one relation removed */
2129 if (e_state == EPOINT_STATE_CONNECT) {
2130 /* use cause from port after connect */
2131 cause = param->disconnectinfo.cause;
2132 location = param->disconnectinfo.location;
2134 /* use multipoint cause if no connect yet */
2135 if (e_multipoint_cause) {
2136 cause = e_multipoint_cause;
2137 location = e_multipoint_location;
2139 cause = CAUSE_NOUSER;
2140 location = LOCATION_PRIVATE_LOCAL;
2144 e_cfnr_call = e_cfnr_release = 0;
2146 /* process hangup */
2147 process_hangup(e_join_cause, e_join_location);
2148 e_multipoint_cause = 0;
2149 e_multipoint_location = 0;
2151 if (message_type == MESSAGE_DISCONNECT) {
2152 /* tone to disconnected end */
2153 SPRINT(buffer, "cause_%02x", cause);
2154 if (ea_endpoint->ep_portlist)
2155 set_tone(ea_endpoint->ep_portlist, buffer);
2157 new_state(EPOINT_STATE_IN_DISCONNECT);
2160 if (ea_endpoint->ep_join_id) {
2161 int haspatterns = 0;
2162 /* check if pattern is available */
2163 if (ea_endpoint->ep_portlist)
2164 if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->early_b)
2165 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
2166 && message_type != MESSAGE_RELEASE) // if we release, we are done
2169 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has patterns.\n", ea_endpoint->ep_serial);
2170 /* indicate patterns */
2171 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2172 message_put(message);
2173 /* connect audio, if not already */
2174 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2175 message->param.audiopath = 1;
2176 message_put(message);
2177 /* send disconnect */
2178 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2179 memcpy(&message->param, param, sizeof(union parameter));
2180 message_put(message);
2181 /* disable encryption if disconnected */
2182 //PERROR("REMOVE ME: state =%d, %d\n", e_crypt_state, e_crypt);
2184 cryptman_message(CI_DISCONNECT_IND, NULL, 0);
2187 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
2190 if (message_type == MESSAGE_RELEASE)
2191 ea_endpoint->free_portlist(portlist);
2192 release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, callcause, portcause */
2193 return; /* must exit here */
2196 /* port MESSAGE_TIMEOUT */
2197 void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type, union parameter *param)
2201 trace_header("TIMEOUT", DIRECTION_IN);
2202 message_type = MESSAGE_DISCONNECT;
2203 switch (param->state) {
2204 case PORT_STATE_OUT_SETUP:
2205 case PORT_STATE_OUT_OVERLAP:
2206 add_trace("state", NULL, "outgoing setup/dialing");
2208 /* no user responding */
2209 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2210 return; /* must exit here */
2212 case PORT_STATE_IN_SETUP:
2213 case PORT_STATE_IN_OVERLAP:
2214 add_trace("state", NULL, "incoming setup/dialing");
2215 param->disconnectinfo.cause = CAUSE_INVALID; /* number incomplete */
2216 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2219 case PORT_STATE_OUT_PROCEEDING:
2220 add_trace("state", NULL, "outgoing proceeding");
2222 param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
2223 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2224 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2225 return; /* must exit here */
2227 case PORT_STATE_IN_PROCEEDING:
2228 add_trace("state", NULL, "incoming proceeding");
2229 param->disconnectinfo.cause = CAUSE_NOUSER;
2230 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL; /* no user responding */
2233 case PORT_STATE_OUT_ALERTING:
2234 add_trace("state", NULL, "outgoing alerting");
2236 param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
2237 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2238 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2239 return; /* must exit here */
2241 case PORT_STATE_CONNECT:
2242 add_trace("state", NULL, "connect");
2244 param->disconnectinfo.cause = CAUSE_NORMAL; /* normal */
2245 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2246 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2247 return; /* must exit here */
2249 case PORT_STATE_IN_ALERTING:
2250 add_trace("state", NULL, "incoming alerting");
2251 param->disconnectinfo.cause = CAUSE_NOANSWER;
2252 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2255 case PORT_STATE_IN_DISCONNECT:
2256 case PORT_STATE_OUT_DISCONNECT:
2257 add_trace("state", NULL, "disconnect");
2259 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
2260 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2261 return; /* must exit here */
2264 param->disconnectinfo.cause = 31; /* normal unspecified */
2265 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2268 /* release call, disconnect isdn */
2270 new_state(EPOINT_STATE_OUT_DISCONNECT);
2271 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2272 SCPY(e_tone, cause);
2274 set_tone(portlist, cause);
2275 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2276 portlist = portlist->next;
2278 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
2281 /* port MESSAGE_NOTIFY */
2282 void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, union parameter *param)
2284 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2286 struct lcr_msg *message;
2287 const char *logtext = "";
2290 /* signal to call tool */
2291 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);
2292 if (param->notifyinfo.notify) {
2293 e_rx_state = track_notify(e_rx_state, param->notifyinfo.notify);
2296 /* if we get notification from stack, local shows if we disabled/enabled audio stream */
2297 if (param->notifyinfo.local) switch(param->notifyinfo.notify) {
2298 case INFO_NOTIFY_REMOTE_HOLD:
2299 case INFO_NOTIFY_USER_SUSPENDED:
2300 /* tell call about it */
2301 if (ea_endpoint->ep_join_id) {
2302 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2303 message->param.audiopath = 0;
2304 message_put(message);
2308 case INFO_NOTIFY_REMOTE_RETRIEVAL:
2309 case INFO_NOTIFY_USER_RESUMED:
2310 /* set volume of rx and tx */
2311 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
2312 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
2314 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2315 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2316 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
2317 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
2318 message_put(message);
2320 /* set current tone */
2322 set_tone(portlist, e_tone);
2323 /* tell call about it */
2324 if (ea_endpoint->ep_join_id) {
2325 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2326 message->param.audiopath = 1;
2327 message_put(message);
2332 /* get name of notify */
2333 switch(param->notifyinfo.notify) {
2338 logtext = "USER_SUSPENDED";
2341 logtext = "BEARER_SERVICE_CHANGED";
2344 logtext = "USER_RESUMED";
2347 logtext = "CONFERENCE_ESTABLISHED";
2350 logtext = "CONFERENCE_DISCONNECTED";
2353 logtext = "OTHER_PARTY_ADDED";
2356 logtext = "ISOLATED";
2359 logtext = "REATTACHED";
2362 logtext = "OTHER_PARTY_ISOLATED";
2365 logtext = "OTHER_PARTY_REATTACHED";
2368 logtext = "OTHER_PARTY_SPLIT";
2371 logtext = "OTHER_PARTY_DISCONNECTED";
2374 logtext = "CONFERENCE_FLOATING";
2377 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
2380 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
2383 logtext = "CALL_IS_A_WAITING_CALL";
2386 logtext = "DIVERSION_ACTIVATED";
2389 logtext = "RESERVED_CT_1";
2392 logtext = "RESERVED_CT_2";
2395 logtext = "REVERSE_CHARGING";
2398 logtext = "REMOTE_HOLD";
2401 logtext = "REMOTE_RETRIEVAL";
2404 logtext = "CALL_IS_DIVERTING";
2407 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
2412 /* notify call if available */
2413 if (ea_endpoint->ep_join_id) {
2414 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOTIFY);
2415 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
2416 message_put(message);
2421 /* port MESSAGE_FACILITY */
2422 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
2424 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2426 struct lcr_msg *message;
2428 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_FACILITY);
2429 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2430 message_put(message);
2433 /* port MESSAGE_SUSPEND */
2434 /* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
2435 void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
2437 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2439 /* epoint is now parked */
2440 ea_endpoint->ep_park = 1;
2441 memcpy(ea_endpoint->ep_park_callid, param->parkinfo.callid, sizeof(ea_endpoint->ep_park_callid));
2442 ea_endpoint->ep_park_len = (param->parkinfo.len>8)?8:param->parkinfo.len;
2444 /* remove port relation */
2445 ea_endpoint->free_portlist(portlist);
2448 /* port MESSAGE_RESUME */
2449 /* NOTE: before resume, the active-notification must be done in order to set call mixer */
2450 void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
2452 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2454 /* epoint is now resumed */
2455 ea_endpoint->ep_park = 0;
2460 /* port sends message to the endpoint
2462 void EndpointAppPBX::ea_message_port(unsigned int port_id, int message_type, union parameter *param)
2464 struct port_list *portlist;
2466 portlist = ea_endpoint->ep_portlist;
2468 if (port_id == portlist->port_id)
2470 portlist = portlist->next;
2473 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);
2477 // PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
2478 switch(message_type) {
2479 case MESSAGE_DATA: /* data from port */
2480 /* check if there is a call */
2481 if (!ea_endpoint->ep_join_id)
2483 /* continue if only one portlist */
2484 if (ea_endpoint->ep_portlist->next != NULL)
2486 /* forward message */
2487 message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2490 case MESSAGE_TONE_EOF: /* tone is end of file */
2491 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
2493 if (e_action->index == ACTION_VBOX_PLAY) {
2496 if (e_action->index == ACTION_EFI) {
2502 case MESSAGE_TONE_COUNTER: /* counter info received */
2503 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);
2505 if (e_action->index == ACTION_VBOX_PLAY) {
2506 e_vbox_counter = param->counter.current;
2507 if (param->counter.max >= 0)
2508 e_vbox_counter_max = param->counter.max;
2512 /* PORT sends SETUP message */
2514 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);
2515 if (e_state!=EPOINT_STATE_IDLE) {
2516 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
2519 port_setup(portlist, message_type, param);
2522 /* PORT sends INFORMATION message */
2523 case MESSAGE_INFORMATION: /* additional digits received */
2524 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);
2525 port_information(portlist, message_type, param);
2528 /* PORT sends FACILITY message */
2529 case MESSAGE_FACILITY:
2530 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2531 port_facility(portlist, message_type, param);
2534 /* PORT sends DTMF message */
2535 case MESSAGE_DTMF: /* dtmf digits received */
2536 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);
2537 port_dtmf(portlist, message_type, param);
2540 /* PORT sends CRYPT message */
2541 case MESSAGE_CRYPT: /* crypt response received */
2542 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) crypt response=%d\n", ea_endpoint->ep_serial, param->crypt.type);
2543 port_crypt(portlist, message_type, param);
2546 /* PORT sends MORE message */
2547 case MESSAGE_OVERLAP:
2548 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);
2549 if (e_state != EPOINT_STATE_OUT_SETUP) {
2550 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);
2553 port_overlap(portlist, message_type, param);
2556 /* PORT sends PROCEEDING message */
2557 case MESSAGE_PROCEEDING: /* port is proceeding */
2558 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);
2559 if (e_state!=EPOINT_STATE_OUT_SETUP
2560 && e_state!=EPOINT_STATE_OUT_OVERLAP) {
2561 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);
2564 port_proceeding(portlist, message_type, param);
2567 /* PORT sends ALERTING message */
2568 case MESSAGE_ALERTING:
2569 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);
2570 if (e_state!=EPOINT_STATE_OUT_SETUP
2571 && e_state!=EPOINT_STATE_OUT_OVERLAP
2572 && e_state!=EPOINT_STATE_OUT_PROCEEDING) {
2573 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);
2576 port_alerting(portlist, message_type, param);
2579 /* PORT sends CONNECT message */
2580 case MESSAGE_CONNECT:
2581 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);
2582 if (e_state!=EPOINT_STATE_OUT_SETUP
2583 && e_state!=EPOINT_STATE_OUT_OVERLAP
2584 && e_state!=EPOINT_STATE_OUT_PROCEEDING
2585 && e_state!=EPOINT_STATE_OUT_ALERTING) {
2586 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
2589 port_connect(portlist, message_type, param);
2592 /* PORT sends DISCONNECT message */
2593 case MESSAGE_DISCONNECT: /* port is disconnected */
2594 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);
2595 port_disconnect_release(portlist, message_type, param);
2598 /* PORT sends a RELEASE message */
2599 case MESSAGE_RELEASE: /* port releases */
2600 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);
2601 /* portlist is release at port_disconnect_release, thanx Paul */
2602 port_disconnect_release(portlist, message_type, param);
2605 /* PORT sends a TIMEOUT message */
2606 case MESSAGE_TIMEOUT:
2607 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);
2608 port_timeout(portlist, message_type, param);
2609 break; /* release */
2611 /* PORT sends a NOTIFY message */
2612 case MESSAGE_NOTIFY:
2613 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);
2614 port_notify(portlist, message_type, param);
2617 /* PORT sends a SUSPEND message */
2618 case MESSAGE_SUSPEND:
2619 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);
2620 port_suspend(portlist, message_type, param);
2621 break; /* suspend */
2623 /* PORT sends a RESUME message */
2624 case MESSAGE_RESUME:
2625 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);
2626 port_resume(portlist, message_type, param);
2630 kann nach dem test gelöscht werden, da eine direkte funktion im join und im mISDN zum austausch der message existiert
2631 /* port assigns bchannel */
2632 case MESSAGE_BCHANNEL: /* bchannel assignment messafe */
2633 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);
2634 /* only one port is expected to be connected to bchannel */
2635 message = message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2636 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_IN);
2642 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);
2645 /* Note: this endpoint may be destroyed, so we MUST return */
2649 /* messages from join
2651 /* join MESSAGE_CRYPT */
2652 void EndpointAppPBX::join_crypt(struct port_list *portlist, int message_type, union parameter *param)
2654 switch(param->crypt.type) {
2655 /* message from remote port to "crypt manager" */
2656 case CU_ACTK_REQ: /* activate key-exchange */
2657 case CU_ACTS_REQ: /* activate shared key */
2658 case CU_DACT_REQ: /* deactivate */
2659 case CU_INFO_REQ: /* request last info message */
2660 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2663 /* message from "crypt manager" to user */
2664 case CU_ACTK_CONF: /* key-echange done */
2665 case CU_ACTS_CONF: /* shared key done */
2666 case CU_DACT_CONF: /* deactivated */
2667 case CU_DACT_IND: /* deactivated */
2668 case CU_ERROR_IND: /* receive error message */
2669 case CU_INFO_IND: /* receive info message */
2670 case CU_INFO_CONF: /* receive info message */
2671 encrypt_result(param->crypt.type, (char *)param->crypt.data);
2675 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);
2679 /* join MESSAGE_INFORMATION */
2680 void EndpointAppPBX::join_information(struct port_list *portlist, int message_type, union parameter *param)
2682 struct lcr_msg *message;
2687 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2688 memcpy(&message->param.information, ¶m->information, sizeof(struct dialing_info));
2689 message_put(message);
2690 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2691 portlist = portlist->next;
2695 /* join MESSAGE_FACILITY */
2696 void EndpointAppPBX::join_facility(struct port_list *portlist, int message_type, union parameter *param)
2698 struct lcr_msg *message;
2700 if (!e_ext.facility && e_ext.number[0]) {
2705 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_FACILITY);
2706 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2707 message_put(message);
2708 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2709 portlist = portlist->next;
2713 /* join MESSAGE_MORE */
2714 void EndpointAppPBX::join_overlap(struct port_list *portlist, int message_type, union parameter *param)
2716 struct lcr_msg *message;
2718 new_state(EPOINT_STATE_IN_OVERLAP);
2721 if (e_join_pattern && e_ext.own_setup) {
2722 /* disconnect audio */
2723 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2724 message->param.audiopath = 0;
2725 message_put(message);
2727 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL) {
2728 if (e_dialinginfo.id[0])
2729 set_tone(portlist, "dialing");
2731 set_tone(portlist, "dialtone");
2734 if (e_dialinginfo.id[0]) {
2735 set_tone(portlist, "dialing");
2737 if (e_ext.number[0])
2738 set_tone(portlist, "dialpbx");
2740 set_tone(portlist, "dialtone");
2744 /* join MESSAGE_PROCEEDING */
2745 void EndpointAppPBX::join_proceeding(struct port_list *portlist, int message_type, union parameter *param)
2747 struct lcr_msg *message;
2749 new_state(EPOINT_STATE_IN_PROCEEDING);
2751 /* own proceeding tone */
2752 if (e_join_pattern) {
2753 /* connect / disconnect audio */
2754 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2755 if (e_ext.own_proceeding)
2756 message->param.audiopath = 0;
2758 message->param.audiopath = 1;
2759 message_put(message);
2761 // UCPY(e_join_tone, "proceeding");
2763 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
2764 message_put(message);
2765 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2767 set_tone(portlist, "proceeding");
2770 /* join MESSAGE_ALERTING */
2771 void EndpointAppPBX::join_alerting(struct port_list *portlist, int message_type, union parameter *param)
2773 struct lcr_msg *message;
2775 new_state(EPOINT_STATE_IN_ALERTING);
2777 /* own alerting tone */
2778 if (e_join_pattern) {
2779 /* connect / disconnect audio */
2780 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2781 if (e_ext.own_alerting)
2782 message->param.audiopath = 0;
2784 message->param.audiopath = 1;
2785 message_put(message);
2788 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
2789 message_put(message);
2790 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2792 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL) {
2793 set_tone(portlist, "ringing");
2796 if (e_ext.number[0])
2797 set_tone(portlist, "ringpbx");
2799 set_tone(portlist, "ringing");
2801 if (e_ext.number[0])
2802 e_dtmf = 1; /* allow dtmf */
2805 /* join MESSAGE_CONNECT */
2806 void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type, union parameter *param)
2808 struct lcr_msg *message;
2810 new_state(EPOINT_STATE_CONNECT);
2811 // UCPY(e_join_tone, "");
2813 if (e_ext.number[0])
2814 e_dtmf = 1; /* allow dtmf */
2817 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_callerinfo));
2819 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
2820 memcpy(&message->param, param, sizeof(union parameter));
2822 /* screen clip if prefix is required */
2823 if (e_ext.number[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0]) {
2824 SCPY(message->param.connectinfo.id, e_ext.clip_prefix);
2825 SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype, options.national, options.international));
2826 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2829 /* use internal caller id */
2830 if (e_ext.number[0] && e_connectinfo.extension[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore)) {
2831 SCPY(message->param.connectinfo.id, e_connectinfo.extension);
2832 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2835 /* handle restricted caller ids */
2836 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);
2837 /* display callerid if desired for extension */
2838 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));
2840 /* use conp, if enabld */
2841 // if (!e_ext.centrex)
2842 // message->param.connectinfo.name[0] = '\0';
2845 message_put(message);
2846 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2848 set_tone(portlist, NULL);
2850 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2851 message->param.audiopath = 1;
2852 message_put(message);
2856 /* join MESSAGE_DISCONNECT MESSAGE_RELEASE */
2857 void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *param)
2860 struct lcr_msg *message;
2861 struct port_list *portlist = NULL;
2864 /* be sure that we are active */
2866 e_tx_state = NOTIFY_STATE_ACTIVE;
2868 /* we are powerdialing, if e_powerdialing is set and limit is not exceeded if given */
2869 if (e_powerdialing && ((e_powercount+1)<e_powerlimit || e_powerlimit<1)) {
2870 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
2872 /* set time for power dialing */
2873 e_powerdialing = now_d + e_powerdelay; /* set redial in the future */
2876 /* set redial tone */
2877 if (ea_endpoint->ep_portlist) {
2880 set_tone(ea_endpoint->ep_portlist, "redial");
2881 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);
2882 /* send proceeding when powerdialing and still setup (avoid dialing timeout) */
2883 if (e_state==EPOINT_STATE_IN_OVERLAP) {
2884 new_state(EPOINT_STATE_IN_PROCEEDING);
2885 if (ea_endpoint->ep_portlist) {
2886 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
2887 message_put(message);
2888 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
2890 /* caused the error, that the first knock sound was not there */
2891 /* set_tone(portlist, "proceeding"); */
2893 /* send display of powerdialing */
2894 if (e_ext.display_dialing) {
2895 portlist = ea_endpoint->ep_portlist;
2897 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
2899 SPRINT(message->param.notifyinfo.display, "Retry %d of %d", e_powercount, e_powerlimit);
2901 SPRINT(message->param.notifyinfo.display, "Retry %d", e_powercount);
2902 message_put(message);
2903 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2904 portlist = portlist->next;
2913 if ((e_state!=EPOINT_STATE_CONNECT
2914 && e_state!=EPOINT_STATE_OUT_DISCONNECT
2915 && e_state!=EPOINT_STATE_IN_OVERLAP
2916 && e_state!=EPOINT_STATE_IN_PROCEEDING
2917 && e_state!=EPOINT_STATE_IN_ALERTING)
2918 || !ea_endpoint->ep_portlist) { /* or no port */
2919 process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
2920 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause); /* RELEASE_TYPE, join, port */
2921 return; /* must exit here */
2924 if (!e_join_cause) {
2925 e_join_cause = param->disconnectinfo.cause;
2926 e_join_location = param->disconnectinfo.location;
2929 /* on release we need the audio again! */
2930 if (message_type == MESSAGE_RELEASE) {
2932 ea_endpoint->ep_join_id = 0;
2934 /* disconnect and select tone */
2935 new_state(EPOINT_STATE_OUT_DISCONNECT);
2936 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2937 /* if own_cause, we must release the join */
2938 if (e_ext.own_cause /* own cause */
2939 || !e_join_pattern) { /* no patterns */
2940 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);
2941 if (message_type != MESSAGE_RELEASE)
2942 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
2944 } else { /* else we enable audio */
2945 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2946 message->param.audiopath = 1;
2947 message_put(message);
2949 /* send disconnect message */
2950 SCPY(e_tone, cause);
2951 portlist = ea_endpoint->ep_portlist;
2953 set_tone(portlist, cause);
2954 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2955 portlist = portlist->next;
2959 /* join MESSAGE_SETUP */
2960 void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, union parameter *param)
2962 struct lcr_msg *message;
2963 // struct interface *interface;
2965 /* if we already in setup state, we just update the dialing with new digits */
2966 if (e_state == EPOINT_STATE_OUT_SETUP
2967 || e_state == EPOINT_STATE_OUT_OVERLAP) {
2968 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we are in setup state, so we do overlap dialing.\n", ea_endpoint->ep_serial);
2969 /* if digits changed, what we have already dialed */
2970 if (!!strncmp(e_dialinginfo.id,param->setup.dialinginfo.id,strlen(e_dialinginfo.id))) {
2971 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);
2972 /* release all ports */
2973 while((portlist = ea_endpoint->ep_portlist)) {
2974 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2975 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2976 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2977 message_put(message);
2978 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2979 ea_endpoint->free_portlist(portlist);
2982 /* disconnect audio */
2983 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2984 message->param.audiopath = 0;
2985 message_put(message);
2987 /* get dialing info */
2988 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
2989 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
2990 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
2991 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
2992 new_state(EPOINT_STATE_OUT_OVERLAP);
2995 e_redial = now_d + 1; /* set redial one second in the future */
2998 /* if we have a pending redial, so we just adjust the dialing number */
3000 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);
3001 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3004 if (!ea_endpoint->ep_portlist) {
3005 PERROR("ERROR: overlap dialing to a NULL port relation\n");
3007 if (ea_endpoint->ep_portlist->next) {
3008 PERROR("ERROR: overlap dialing to a port_list port relation\n");
3010 if (e_state == EPOINT_STATE_OUT_SETUP) {
3012 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);
3013 SCAT(e_dialing_queue, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3016 /* get what we have not dialed yet */
3017 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));
3018 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
3019 SCPY(message->param.information.id, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3020 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
3021 message_put(message);
3022 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3024 /* always store what we have dialed or queued */
3025 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3029 if (e_state != EPOINT_STATE_IDLE) {
3030 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
3033 /* if an internal extension is dialed, copy that number */
3034 if (param->setup.dialinginfo.itype==INFO_ITYPE_ISDN_EXTENSION || param->setup.dialinginfo.itype==INFO_ITYPE_VBOX)
3035 SCPY(e_ext.number, param->setup.dialinginfo.id);
3036 /* if an internal extension is dialed, get extension's info about caller */
3037 if (e_ext.number[0]) {
3038 if (!read_extension(&e_ext, e_ext.number)) {
3039 e_ext.number[0] = '\0';
3040 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the called terminal='%s' is not found in directory tree!\n", ea_endpoint->ep_serial, e_ext.number);
3044 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3045 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3046 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3047 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3049 /* process (voice over) data calls */
3050 if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO) {
3051 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) handling data call as audio call: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
3052 memset(&e_capainfo, 0, sizeof(e_capainfo));
3053 e_capainfo.bearer_capa = INFO_BC_AUDIO;
3054 e_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
3055 e_capainfo.bearer_info1 = (options.law=='u')?INFO_INFO1_ULAW:INFO_INFO1_ALAW;
3058 new_state(EPOINT_STATE_OUT_SETUP);
3059 /* call special setup routine */
3063 /* join MESSAGE_mISDNSIGNAL */
3064 void EndpointAppPBX::join_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param)
3066 struct lcr_msg *message;
3069 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
3070 memcpy(&message->param, param, sizeof(union parameter));
3071 message_put(message);
3072 portlist = portlist->next;
3076 /* join MESSAGE_NOTIFY */
3077 void EndpointAppPBX::join_notify(struct port_list *portlist, int message_type, union parameter *param)
3079 struct lcr_msg *message;
3082 if (param->notifyinfo.notify) {
3083 new_state = track_notify(e_tx_state, param->notifyinfo.notify);
3084 // /* if notification was generated locally, we turn hold music on/off */
3085 // if (param->notifyinfo.local)
3086 // 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)
3090 if (new_state!=NOTIFY_STATE_HOLD && new_state!=NOTIFY_STATE_SUSPEND) {
3091 if (!strcmp(e_tone, "hold")) { // don't interrupt other tones
3093 set_tone(portlist, "");
3094 portlist = portlist->next;
3097 portlist = ea_endpoint->ep_portlist;
3102 if (new_state==NOTIFY_STATE_HOLD || new_state==NOTIFY_STATE_SUSPEND) {
3104 set_tone(portlist, "hold");
3105 portlist = portlist->next;
3107 portlist = ea_endpoint->ep_portlist;
3112 /* save new state */
3113 e_tx_state = new_state;
3116 /* notify port(s) about it */
3118 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3119 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
3120 /* handle restricted caller ids */
3121 apply_callerid_restriction(&e_ext, message->param.notifyinfo.id, &message->param.notifyinfo.ntype, &message->param.notifyinfo.present, 0, message->param.notifyinfo.extension, NULL);
3122 /* display callerid if desired for extension */
3123 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));
3124 message_put(message);
3125 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3126 portlist = portlist->next;
3130 /* JOIN sends messages to the endpoint
3132 void EndpointAppPBX::ea_message_join(unsigned int join_id, int message_type, union parameter *param)
3134 struct port_list *portlist;
3135 struct lcr_msg *message;
3138 PERROR("EPOINT(%d) error: JOIN == NULL.\n", ea_endpoint->ep_serial);
3142 portlist = ea_endpoint->ep_portlist;
3144 /* send MESSAGE_DATA to port */
3145 if (message_type == MESSAGE_DATA) {
3146 if (join_id == ea_endpoint->ep_join_id) { // still linked with JOIN
3147 /* skip if no port relation */
3150 /* skip if more than one port relation */
3153 /* forward audio data to port */
3154 message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3159 // 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);
3160 switch(message_type) {
3161 /* JOIN SENDS TONE message */
3163 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);
3164 set_tone(portlist, param->tone.name);
3167 /* JOIN SENDS CRYPT message */
3169 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);
3170 join_crypt(portlist, message_type, param);
3173 /* JOIN sends INFORMATION message */
3174 case MESSAGE_INFORMATION:
3175 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);
3176 join_information(portlist, message_type, param);
3179 /* JOIN sends FACILITY message */
3180 case MESSAGE_FACILITY:
3181 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);
3182 join_facility(portlist, message_type, param);
3185 /* JOIN sends OVERLAP message */
3186 case MESSAGE_OVERLAP:
3187 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);
3188 if (e_state!=EPOINT_STATE_IN_SETUP
3189 && e_state!=EPOINT_STATE_IN_OVERLAP) {
3190 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3193 join_overlap(portlist, message_type, param);
3196 /* JOIN sends PROCEEDING message */
3197 case MESSAGE_PROCEEDING:
3198 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);
3199 if(e_state!=EPOINT_STATE_IN_OVERLAP) {
3200 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3203 join_proceeding(portlist, message_type, param);
3206 /* JOIN sends ALERTING message */
3207 case MESSAGE_ALERTING:
3208 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);
3209 if (e_state!=EPOINT_STATE_IN_OVERLAP
3210 && e_state!=EPOINT_STATE_IN_PROCEEDING) {
3211 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state.\n", ea_endpoint->ep_serial);
3214 join_alerting(portlist, message_type, param);
3217 /* JOIN sends CONNECT message */
3218 case MESSAGE_CONNECT:
3219 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);
3220 if (e_state!=EPOINT_STATE_IN_OVERLAP
3221 && e_state!=EPOINT_STATE_IN_PROCEEDING
3222 && e_state!=EPOINT_STATE_IN_ALERTING) {
3223 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
3226 join_connect(portlist, message_type, param);
3229 /* JOIN sends DISCONNECT/RELEASE message */
3230 case MESSAGE_DISCONNECT: /* JOIN disconnect */
3231 case MESSAGE_RELEASE: /* JOIN releases */
3232 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);
3233 join_disconnect_release(message_type, param);
3236 /* JOIN sends SETUP message */
3238 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);
3239 join_setup(portlist, message_type, param);
3242 /* JOIN sends special mISDNSIGNAL message */
3243 case MESSAGE_mISDNSIGNAL: /* isdn message to port */
3244 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);
3245 join_mISDNsignal(portlist, message_type, param);
3249 kann nach dem test gelöscht werden, da eine direkte funktion im join und im mISDN zum austausch der message existiert
3250 /* JOIN requests bchannel */
3251 case MESSAGE_BCHANNEL: /* indicates the need of own bchannel access */
3252 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);
3253 /* only one port is expected to be connected to bchannel */
3260 set_tone(portlist, NULL);
3261 message = message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3262 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3266 /* JOIN has pattern available */
3267 case MESSAGE_PATTERN: /* indicating pattern available */
3268 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);
3269 if (!e_join_pattern) {
3270 PDEBUG(DEBUG_EPOINT, "-> pattern becomes available\n");
3274 set_tone(portlist, NULL);
3275 portlist = portlist->next;
3277 /* connect our audio tx and rx (blueboxing should be possibe before connect :)*/
3278 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3279 message->param.audiopath = 1;
3280 message_put(message);
3284 /* JOIN has no pattern available */
3285 case MESSAGE_NOPATTERN: /* indicating no pattern available */
3286 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);
3287 if (e_join_pattern) {
3288 PDEBUG(DEBUG_EPOINT, "-> pattern becomes unavailable\n");
3290 /* disconnect our audio tx and rx */
3291 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3292 message->param.audiopath = 0;
3293 message_put(message);
3298 /* JOIN (dunno at the moment) */
3299 case MESSAGE_REMOTE_AUDIO:
3300 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);
3301 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3302 message->param.audiopath = param->channel;
3303 message_put(message);
3307 /* JOIN sends a notify message */
3308 case MESSAGE_NOTIFY:
3309 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);
3310 join_notify(portlist, message_type, param);
3313 /* JOIN wants keypad / dtmf */
3314 case MESSAGE_ENABLEKEYPAD:
3315 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);
3318 trace_header("ENABLE KEYPAD", DIRECTION_NONE);
3323 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);
3328 /* pick_join will connect the first incoming call found. the endpoint
3329 * will receivce a MESSAGE_CONNECT.
3331 int match_list(char *list, char *item)
3333 char *end, *next = NULL;
3335 /* no list make matching */
3340 /* eliminate white spaces */
3341 while (*list <= ' ')
3347 /* if end of list is reached, we return */
3348 if (list[0] == '\0')
3350 /* if we have more than one entry (left) */
3351 if ((end = strchr(list, ',')))
3354 next = end = strchr(list, '\0');
3355 while (*(end-1) <= ' ')
3357 /* if string part matches item */
3358 if (!strncmp(list, item, end-list))
3364 void EndpointAppPBX::pick_join(char *extensions)
3366 struct lcr_msg *message;
3367 struct port_list *portlist;
3369 class EndpointAppPBX *eapp, *found;
3371 class JoinPBX *joinpbx;
3372 struct join_relation *relation;
3375 /* find an endpoint that is ringing internally or vbox with higher priority */
3378 eapp = apppbx_first;
3380 if (eapp!=this && ea_endpoint->ep_portlist) {
3381 portlist = eapp->ea_endpoint->ep_portlist;
3383 if ((port = find_port_id(portlist->port_id))) {
3384 if (port->p_type == PORT_TYPE_VBOX_OUT) {
3385 if (match_list(extensions, eapp->e_ext.number)) {
3391 if ((port->p_type==PORT_TYPE_DSS1_NT_OUT || port->p_type==PORT_TYPE_DSS1_TE_OUT || port->p_type==PORT_TYPE_GSM_OUT)
3392 && port->p_state==PORT_STATE_OUT_ALERTING)
3393 if (match_list(extensions, eapp->e_ext.number)) {
3397 portlist = portlist->next;
3405 /* if no endpoint found */
3407 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);
3409 set_tone(ea_endpoint->ep_portlist, "cause_10");
3410 message_disconnect_port(ea_endpoint->ep_portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
3411 new_state(EPOINT_STATE_OUT_DISCONNECT);
3416 if (ea_endpoint->ep_join_id) {
3417 PERROR("EPOINT(%d) we already have a join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3420 if (!eapp->ea_endpoint->ep_join_id) {
3421 PERROR("EPOINT(%d) ringing endpoint has no join.\n", ea_endpoint->ep_serial);
3424 join = find_join_id(eapp->ea_endpoint->ep_join_id);
3426 PERROR("EPOINT(%d) ringing endpoint's join not found.\n", ea_endpoint->ep_serial);
3429 if (join->j_type != JOIN_TYPE_PBX) {
3430 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ringing endpoint's join is not a PBX join, so we must reject.\n", ea_endpoint->ep_serial);
3433 joinpbx = (class JoinPBX *)join;
3434 relation = joinpbx->j_relation;
3436 PERROR("EPOINT(%d) ringing endpoint's join has no relation. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3439 while (relation->epoint_id != eapp->ea_endpoint->ep_serial) {
3440 relation = relation->next;
3442 PERROR("EPOINT(%d) ringing endpoint's join has no relation to that join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3447 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found ringing endpoint: %d.\n", ea_endpoint->ep_serial, eapp->ea_endpoint->ep_serial);
3449 if (options.deb & DEBUG_EPOINT) {
3450 class Join *debug_c = join_first;
3451 class Endpoint *debug_e = epoint_first;
3452 class Port *debug_p = port_first;
3454 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(before)");
3456 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3458 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3459 debug_c = debug_c->next;
3461 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3463 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3464 debug_e = debug_e->next;
3466 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3468 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld (active)\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3469 debug_p = debug_p->next;
3474 ea_endpoint->ep_join_id = eapp->ea_endpoint->ep_join_id; /* we get the join */
3475 relation->epoint_id = ea_endpoint->ep_serial; /* the join gets us */
3476 eapp->ea_endpoint->ep_join_id = 0; /* the ringing endpoint will get disconnected */
3478 /* connnecting our endpoint */
3479 new_state(EPOINT_STATE_CONNECT);
3480 if (e_ext.number[0])
3482 set_tone(ea_endpoint->ep_portlist, NULL);
3484 /* now we send a release to the ringing endpoint */
3485 message = message_create(ea_endpoint->ep_join_id, eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3486 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
3487 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3488 message_put(message);
3490 /* we send a connect to the join with our caller id */
3491 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CONNECT);
3492 SCPY(message->param.connectinfo.id, e_callerinfo.id);
3493 message->param.connectinfo.present = e_callerinfo.present;
3494 message->param.connectinfo.screen = e_callerinfo.screen;
3495 message->param.connectinfo.itype = e_callerinfo.itype;
3496 message->param.connectinfo.ntype = e_callerinfo.ntype;
3497 message_put(message);
3499 /* we send a connect to our port with the remote callerid */
3500 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3501 SCPY(message->param.connectinfo.id, eapp->e_callerinfo.id);
3502 message->param.connectinfo.present = eapp->e_callerinfo.present;
3503 message->param.connectinfo.screen = eapp->e_callerinfo.screen;
3504 message->param.connectinfo.itype = eapp->e_callerinfo.itype;
3505 message->param.connectinfo.ntype = eapp->e_callerinfo.ntype;
3506 /* handle restricted caller ids */
3507 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);
3508 /* display callerid if desired for extension */
3509 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));
3510 message_put(message);
3512 /* we send a connect to the audio path (not for vbox) */
3513 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3514 message->param.audiopath = 1;
3515 message_put(message);
3517 /* beeing paranoid, we make call update */
3518 joinpbx->j_updatebridge = 1;
3520 if (options.deb & DEBUG_EPOINT) {
3521 class Join *debug_c = join_first;
3522 class Endpoint *debug_e = epoint_first;
3523 class Port *debug_p = port_first;
3525 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(after)");
3527 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3529 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3530 debug_c = debug_c->next;
3532 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3534 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3535 debug_e = debug_e->next;
3537 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3539 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3540 debug_p = debug_p->next;
3546 /* join calls (look for a join that is on hold (same isdn interface/terminal))
3548 void EndpointAppPBX::join_join(void)
3550 struct lcr_msg *message;
3551 struct join_relation *our_relation, *other_relation;
3552 struct join_relation **our_relation_pointer, **other_relation_pointer;
3553 class Join *our_join, *other_join;
3554 class JoinPBX *our_joinpbx, *other_joinpbx;
3555 class EndpointAppPBX *other_eapp; class Endpoint *temp_epoint;
3556 class Port *our_port, *other_port;
3557 class Pdss1 *our_pdss1, *other_pdss1;
3559 /* are we a candidate to join a join? */
3560 our_join = find_join_id(ea_endpoint->ep_join_id);
3562 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3565 if (our_join->j_type != JOIN_TYPE_PBX) {
3566 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: join is not a pbx join.\n", ea_endpoint->ep_serial);
3569 our_joinpbx = (class JoinPBX *)our_join;
3570 if (!ea_endpoint->ep_portlist) {
3571 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
3574 if (!e_ext.number[0]) {
3575 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
3578 our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
3580 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
3583 if ((our_port->p_type&PORT_CLASS_mISDN_MASK) != PORT_CLASS_mISDN_DSS1) {
3584 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not isdn.\n", ea_endpoint->ep_serial);
3587 our_pdss1 = (class Pdss1 *)our_port;
3589 /* find an endpoint that is on hold and has the same mISDNport that we are on */
3590 other_eapp = apppbx_first;
3592 if (other_eapp == this) {
3593 other_eapp = other_eapp->next;
3596 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);
3597 if (other_eapp->e_ext.number[0] /* has terminal */
3598 && other_eapp->ea_endpoint->ep_portlist /* has port */
3599 && other_eapp->ea_endpoint->ep_join_id) { /* has join */
3600 other_port = find_port_id(other_eapp->ea_endpoint->ep_portlist->port_id);
3601 if (other_port) { /* port still exists */
3602 if (other_port->p_type==PORT_TYPE_DSS1_NT_OUT
3603 || other_port->p_type==PORT_TYPE_DSS1_NT_IN) { /* port is isdn nt-mode */
3604 other_pdss1 = (class Pdss1 *)other_port;
3605 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);
3606 if (other_pdss1->p_m_hold /* port is on hold */
3607 && other_pdss1->p_m_mISDNport == our_pdss1->p_m_mISDNport /* same isdn interface */
3608 && other_pdss1->p_m_d_ces == our_pdss1->p_m_d_ces) /* same tei+sapi */
3611 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of other type!\n", ea_endpoint->ep_serial);
3614 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port doesn't exist enymore.\n", ea_endpoint->ep_serial);
3617 other_eapp = other_eapp->next;
3620 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn terminal.\n", ea_endpoint->ep_serial);
3623 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port with same terminal found.\n", ea_endpoint->ep_serial);
3625 /* if we have the same join */
3626 if (other_eapp->ea_endpoint->ep_join_id == ea_endpoint->ep_join_id) {
3627 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we and the other have the same join.\n", ea_endpoint->ep_serial);
3630 other_join = find_join_id(other_eapp->ea_endpoint->ep_join_id);
3632 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3635 if (other_join->j_type != JOIN_TYPE_PBX) {
3636 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join is not a pbx join.\n", ea_endpoint->ep_serial);
3639 other_joinpbx = (class JoinPBX *)other_join;
3640 if (our_joinpbx->j_partyline && other_joinpbx->j_partyline) {
3641 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both joins are partylines.\n", ea_endpoint->ep_serial);
3645 /* remove relation to endpoint for join on hold */
3646 other_relation = other_joinpbx->j_relation;
3647 other_relation_pointer = &other_joinpbx->j_relation;
3648 while(other_relation) {
3649 if (other_relation->epoint_id == other_eapp->ea_endpoint->ep_serial) {
3650 /* detach other endpoint on hold */
3651 *other_relation_pointer = other_relation->next;
3652 FREE(other_relation, sizeof(struct join_relation));
3654 other_relation = *other_relation_pointer;
3655 other_eapp->ea_endpoint->ep_join_id = 0;
3659 /* change join/hold pointer of endpoint to the new join */
3660 temp_epoint = find_epoint_id(other_relation->epoint_id);
3662 if (temp_epoint->ep_join_id == other_join->j_serial)
3663 temp_epoint->ep_join_id = our_join->j_serial;
3666 other_relation_pointer = &other_relation->next;
3667 other_relation = other_relation->next;
3669 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint on hold removed, other enpoints on join relinked (to our join).\n", ea_endpoint->ep_serial);
3671 /* join call relations */
3672 our_relation = our_joinpbx->j_relation;
3673 our_relation_pointer = &our_joinpbx->j_relation;
3674 while(our_relation) {
3675 our_relation_pointer = &our_relation->next;
3676 our_relation = our_relation->next;
3678 *our_relation_pointer = other_joinpbx->j_relation;
3679 other_joinpbx->j_relation = NULL;
3680 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) relations joined.\n", ea_endpoint->ep_serial);
3682 /* release endpoint on hold */
3683 message = message_create(other_joinpbx->j_serial, other_eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3684 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */
3685 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3686 message_put(message);
3688 /* if we are not a partyline, we get partyline state from other join */
3689 our_joinpbx->j_partyline += other_joinpbx->j_partyline;
3691 /* remove empty join */
3693 PDEBUG(DEBUG_EPOINT, "EPOINT(%d)d-join completely removed!\n");
3695 /* mixer must update */
3696 our_joinpbx->j_updatebridge = 1; /* update mixer flag */
3698 /* we send a retrieve to that endpoint */
3699 // mixer will update the hold-state of the join and send it to the endpoints is changes
3703 /* check if we have an external call
3704 * this is used to check for encryption ability
3706 int EndpointAppPBX::check_external(const char **errstr, class Port **port)
3708 struct join_relation *relation;
3710 class JoinPBX *joinpbx;
3711 class Endpoint *epoint;
3713 /* some paranoia check */
3714 if (!ea_endpoint->ep_portlist) {
3715 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we have no port.\n", ea_endpoint->ep_serial);
3716 *errstr = "No Call";
3719 if (!e_ext.number[0]) {
3720 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we are not internal extension.\n", ea_endpoint->ep_serial);
3721 *errstr = "No Call";
3725 /* check if we have a join with 2 parties */
3726 join = find_join_id(ea_endpoint->ep_join_id);
3728 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have currently no join.\n", ea_endpoint->ep_serial);
3729 *errstr = "No Call";
3732 if (join->j_type != JOIN_TYPE_PBX) {
3733 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join is not a pbx join.\n", ea_endpoint->ep_serial);
3734 *errstr = "No PBX Call";
3737 joinpbx = (class JoinPBX *)join;
3738 relation = joinpbx->j_relation;
3740 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no relation.\n", ea_endpoint->ep_serial);
3741 *errstr = "No Call";
3744 if (!relation->next) {
3745 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd relation.\n", ea_endpoint->ep_serial);
3746 *errstr = "No Call";
3749 if (relation->next->next) {
3750 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has more than two relations.\n", ea_endpoint->ep_serial);
3751 *errstr = "Err: Conference";
3754 if (relation->epoint_id == ea_endpoint->ep_serial) {
3755 relation = relation->next;
3756 if (relation->epoint_id == ea_endpoint->ep_serial) {
3757 PERROR("EPOINT(%d) SOFTWARE ERROR: both join relations are related to our endpoint.\n", ea_endpoint->ep_serial);
3758 *errstr = "Software Error";
3763 /* check remote port for external call */
3764 epoint = find_epoint_id(relation->epoint_id);
3766 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd endpoint.\n", ea_endpoint->ep_serial);
3767 *errstr = "No Call";
3770 if (!epoint->ep_portlist) {
3771 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not port.\n", ea_endpoint->ep_serial);
3772 *errstr = "No Call";
3775 *port = find_port_id(epoint->ep_portlist->port_id);
3777 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has an none existing port.\n", ea_endpoint->ep_serial);
3778 *errstr = "No Call";
3781 if (((*port)->p_type&PORT_CLASS_mISDN_MASK)!=PORT_CLASS_mISDN_DSS1) { /* port is not external isdn */
3782 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not an external port.\n", ea_endpoint->ep_serial);
3783 *errstr = "No Ext Call";
3786 if ((*port)->p_state != PORT_STATE_CONNECT) {
3787 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint's port is not in connected state.\n", ea_endpoint->ep_serial);
3788 *errstr = "No Ext Connect";
3794 void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsigned int port_id, int dir)
3796 const char *logtext = "unknown";
3799 switch(message_type) {
3801 trace_header("SETUP", dir);
3802 if (dir == DIRECTION_OUT)
3803 add_trace("to", NULL, "CH(%lu)", port_id);
3804 if (dir == DIRECTION_IN)
3805 add_trace("from", NULL, "CH(%lu)", port_id);
3806 if (param->setup.callerinfo.extension[0])
3807 add_trace("extension", NULL, "%s", param->setup.callerinfo.extension);
3808 add_trace("caller id", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype, options.national, options.international));
3809 switch(param->setup.callerinfo.present) {
3810 case INFO_PRESENT_RESTRICTED:
3811 add_trace("caller id", "present", "restricted");
3813 case INFO_PRESENT_ALLOWED:
3814 add_trace("caller id", "present", "allowed");
3817 add_trace("caller id", "present", "not available");
3819 if (param->setup.callerinfo.ntype2) {
3820 add_trace("caller id2", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id2, param->setup.callerinfo.ntype2, options.national, options.international));
3821 switch(param->setup.callerinfo.present) {
3822 case INFO_PRESENT_RESTRICTED:
3823 add_trace("caller id2", "present", "restricted");
3825 case INFO_PRESENT_ALLOWED:
3826 add_trace("caller id2", "present", "allowed");
3829 add_trace("caller id2", "present", "not available");
3832 if (param->setup.redirinfo.id[0]) {
3833 add_trace("redir'ing", "number", "%s", numberrize_callerinfo(param->setup.redirinfo.id, param->setup.redirinfo.ntype, options.national, options.international));
3834 switch(param->setup.redirinfo.present) {
3835 case INFO_PRESENT_RESTRICTED:
3836 add_trace("redir'ing", "present", "restricted");
3838 case INFO_PRESENT_ALLOWED:
3839 add_trace("redir'ing", "present", "allowed");
3842 add_trace("redir'ing", "present", "not available");
3845 if (param->setup.dialinginfo.id[0])
3846 add_trace("dialing", NULL, "%s", param->setup.dialinginfo.id);
3847 if (param->setup.dialinginfo.display[0])
3848 add_trace("display", NULL, "%s", param->setup.dialinginfo.display);
3849 if (param->setup.dialinginfo.sending_complete)
3850 add_trace("complete", NULL, "true", param->setup.dialinginfo.sending_complete);
3854 case MESSAGE_OVERLAP:
3855 trace_header("SETUP ACKNOWLEDGE", dir);
3856 if (dir == DIRECTION_OUT)
3857 add_trace("to", NULL, "CH(%lu)", port_id);
3858 if (dir == DIRECTION_IN)
3859 add_trace("from", NULL, "CH(%lu)", port_id);
3863 case MESSAGE_PROCEEDING:
3864 trace_header("PROCEEDING", dir);
3865 if (dir == DIRECTION_OUT)
3866 add_trace("to", NULL, "CH(%lu)", port_id);
3867 if (dir == DIRECTION_IN)
3868 add_trace("from", NULL, "CH(%lu)", port_id);
3872 case MESSAGE_ALERTING:
3873 trace_header("ALERTING", dir);
3874 if (dir == DIRECTION_OUT)
3875 add_trace("to", NULL, "CH(%lu)", port_id);
3876 if (dir == DIRECTION_IN)
3877 add_trace("from", NULL, "CH(%lu)", port_id);
3881 case MESSAGE_CONNECT:
3882 trace_header("CONNECT", dir);
3883 if (dir == DIRECTION_OUT)
3884 add_trace("to", NULL, "CH(%lu)", port_id);
3885 if (dir == DIRECTION_IN)
3886 add_trace("from", NULL, "CH(%lu)", port_id);
3887 if (param->connectinfo.extension[0])
3888 add_trace("extension", NULL, "%s", param->connectinfo.extension);
3889 add_trace("connect id", "number", "%s", numberrize_callerinfo(param->connectinfo.id, param->connectinfo.ntype, options.national, options.international));
3890 switch(param->connectinfo.present) {
3891 case INFO_PRESENT_RESTRICTED:
3892 add_trace("connect id", "present", "restricted");
3894 case INFO_PRESENT_ALLOWED:
3895 add_trace("connect id", "present", "allowed");
3898 add_trace("connect id", "present", "not available");
3900 if (param->connectinfo.display[0])
3901 add_trace("display", NULL, "%s", param->connectinfo.display);
3905 case MESSAGE_DISCONNECT:
3906 case MESSAGE_RELEASE:
3907 if (message_type == MESSAGE_DISCONNECT)
3908 trace_header("DISCONNECT", dir);
3910 trace_header("RELEASE", 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);
3915 add_trace("cause", "value", "%d", param->disconnectinfo.cause);
3916 switch(param->disconnectinfo.location) {
3918 add_trace("cause", "location", "0-User");
3920 case LOCATION_PRIVATE_LOCAL:
3921 add_trace("cause", "location", "1-Local-PBX");
3923 case LOCATION_PUBLIC_LOCAL:
3924 add_trace("cause", "location", "2-Local-Exchange");
3926 case LOCATION_TRANSIT:
3927 add_trace("cause", "location", "3-Transit");
3929 case LOCATION_PUBLIC_REMOTE:
3930 add_trace("cause", "location", "4-Remote-Exchange");
3932 case LOCATION_PRIVATE_REMOTE:
3933 add_trace("cause", "location", "5-Remote-PBX");
3935 case LOCATION_INTERNATIONAL:
3936 add_trace("cause", "location", "7-International-Exchange");
3938 case LOCATION_BEYOND:
3939 add_trace("cause", "location", "10-Beyond-Interworking");
3942 add_trace("cause", "location", "%d", param->disconnectinfo.location);
3944 if (param->disconnectinfo.display[0])
3945 add_trace("display", NULL, "%s", param->disconnectinfo.display);
3949 case MESSAGE_NOTIFY:
3950 switch(param->notifyinfo.notify) {
3955 logtext = "USER_SUSPENDED";
3958 logtext = "BEARER_SERVICE_CHANGED";
3961 logtext = "USER_RESUMED";
3964 logtext = "CONFERENCE_ESTABLISHED";
3967 logtext = "CONFERENCE_DISCONNECTED";
3970 logtext = "OTHER_PARTY_ADDED";
3973 logtext = "ISOLATED";
3976 logtext = "REATTACHED";
3979 logtext = "OTHER_PARTY_ISOLATED";
3982 logtext = "OTHER_PARTY_REATTACHED";
3985 logtext = "OTHER_PARTY_SPLIT";
3988 logtext = "OTHER_PARTY_DISCONNECTED";
3991 logtext = "CONFERENCE_FLOATING";
3994 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
3997 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
4000 logtext = "CALL_IS_A_WAITING_CALL";
4003 logtext = "DIVERSION_ACTIVATED";
4006 logtext = "RESERVED_CT_1";
4009 logtext = "RESERVED_CT_2";
4012 logtext = "REVERSE_CHARGING";
4015 logtext = "REMOTE_HOLD";
4018 logtext = "REMOTE_RETRIEVAL";
4021 logtext = "CALL_IS_DIVERTING";
4024 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
4028 trace_header("NOTIFY", dir);
4029 if (dir == DIRECTION_OUT)
4030 add_trace("to", NULL, "CH(%lu)", port_id);
4031 if (dir == DIRECTION_IN)
4032 add_trace("from", NULL, "CH(%lu)", port_id);
4033 if (param->notifyinfo.notify)
4034 add_trace("indicator", NULL, "%s", logtext);
4035 if (param->notifyinfo.id[0]) {
4036 add_trace("redir'on", "number", "%s", numberrize_callerinfo(param->notifyinfo.id, param->notifyinfo.ntype, options.national, options.international));
4037 switch(param->notifyinfo.present) {
4038 case INFO_PRESENT_RESTRICTED:
4039 add_trace("redir'on", "present", "restricted");
4041 case INFO_PRESENT_ALLOWED:
4042 add_trace("redir'on", "present", "allowed");
4045 add_trace("redir'on", "present", "not available");
4048 if (param->notifyinfo.display[0])
4049 add_trace("display", NULL, "%s", param->notifyinfo.display);
4053 case MESSAGE_INFORMATION:
4054 trace_header("INFORMATION", dir);
4055 if (dir == DIRECTION_OUT)
4056 add_trace("to", NULL, "CH(%lu)", port_id);
4057 if (dir == DIRECTION_IN)
4058 add_trace("from", NULL, "CH(%lu)", port_id);
4059 if (param->information.id[0])
4060 add_trace("dialing", NULL, "%s", param->information.id);
4061 if (param->information.display[0])
4062 add_trace("display", NULL, "%s", param->information.display);
4063 if (param->information.sending_complete)
4064 add_trace("complete", NULL, "true", param->information.sending_complete);
4068 case MESSAGE_FACILITY:
4069 trace_header("FACILITY", dir);
4070 if (dir == DIRECTION_OUT)
4071 add_trace("to", NULL, "CH(%lu)", port_id);
4072 if (dir == DIRECTION_IN)
4073 add_trace("from", NULL, "CH(%lu)", port_id);
4078 trace_header("TONE", dir);
4079 if (dir == DIRECTION_OUT)
4080 add_trace("to", NULL, "CH(%lu)", port_id);
4081 if (dir == DIRECTION_IN)
4082 add_trace("from", NULL, "CH(%lu)", port_id);
4083 if (param->tone.name[0]) {
4084 add_trace("directory", NULL, "%s", param->tone.dir[0]?param->tone.dir:"default");
4085 add_trace("name", NULL, "%s", param->tone.name);
4087 add_trace("off", NULL, NULL);
4091 case MESSAGE_SUSPEND:
4092 case MESSAGE_RESUME:
4093 if (message_type == MESSAGE_SUSPEND)
4094 trace_header("SUSPEND", dir);
4096 trace_header("RESUME", dir);
4097 if (dir == DIRECTION_OUT)
4098 add_trace("to", NULL, "CH(%lu)", port_id);
4099 if (dir == DIRECTION_IN)
4100 add_trace("from", NULL, "CH(%lu)", port_id);
4101 if (param->parkinfo.len)
4102 add_trace("length", NULL, "%d", param->parkinfo.len);
4107 case MESSAGE_BCHANNEL:
4108 trace_header("BCHANNEL", dir);
4109 switch(param->bchannel.type) {
4110 case BCHANNEL_REQUEST:
4111 add_trace("type", NULL, "request");
4113 case BCHANNEL_ASSIGN:
4114 add_trace("type", NULL, "assign");
4116 case BCHANNEL_ASSIGN_ACK:
4117 add_trace("type", NULL, "assign_ack");
4119 case BCHANNEL_REMOVE:
4120 add_trace("type", NULL, "remove");
4122 case BCHANNEL_REMOVE_ACK:
4123 add_trace("type", NULL, "remove_ack");
4126 if (param->bchannel.addr)
4127 add_trace("address", NULL, "%x", param->bchannel.addr);
4133 PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message_type);
4137 void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cause, int location, const char *display)
4139 struct lcr_msg *message;
4143 if (!portlist->port_id)
4146 if (!e_connectedmode) {
4147 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT);
4148 message->param.disconnectinfo.cause = cause;
4149 message->param.disconnectinfo.location = location;
4151 SCPY(message->param.disconnectinfo.display, display);
4153 SCPY(message->param.disconnectinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4155 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
4157 SCPY(message->param.notifyinfo.display, display);
4159 SCPY(message->param.notifyinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4161 message_put(message);
4162 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);