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;
554 interface = interface_first;
556 /* first find the given interface or, if not given, one with no extension */
561 /* check for given interface */
563 if (!strcasecmp(interface->name, ifname)) {
564 /* found explicit interface */
565 trace_header("CHANNEL SELECTION (found interface)", DIRECTION_NONE);
566 add_trace("interface", NULL, "%s", ifname);
572 if (!interface->extension) {
573 /* found non extension */
574 trace_header("CHANNEL SELECTION (found non extension interface)", DIRECTION_NONE);
575 add_trace("interface", NULL, "%s", interface->name);
581 interface = interface->next;
585 /* see if interface has ports */
586 if (!interface->ifport) {
588 trace_header("CHANNEL SELECTION (active ports, skipping)", DIRECTION_NONE);
589 add_trace("interface", NULL, "%s", interface->name);
591 interface = interface->next;
595 /* select port by algorithm */
596 ifport_start = interface->ifport;
598 if (interface->hunt == HUNT_ROUNDROBIN) {
599 while(ifport_start->next && index<interface->hunt_next) {
600 ifport_start = ifport_start->next;
603 trace_header("CHANNEL SELECTION (starting round-robin)", DIRECTION_NONE);
604 add_trace("port", NULL, "%d", ifport_start->portnum);
605 add_trace("position", NULL, "%d", index);
610 ifport = ifport_start;
613 /* see if port is available */
614 if (!ifport->mISDNport) {
615 trace_header("CHANNEL SELECTION (port not available, skipping)", DIRECTION_NONE);
616 add_trace("port", NULL, "%d", ifport->portnum);
617 add_trace("position", NULL, "%d", index);
621 mISDNport = ifport->mISDNport;
623 /* see if port is administratively blocked */
625 trace_header("CHANNEL SELECTION (port blocked by admin, skipping)", DIRECTION_NONE);
626 add_trace("port", NULL, "%d", ifport->portnum);
627 add_trace("position", NULL, "%d", index);
632 /* see if link is up on PTP*/
633 if (mISDNport->l2hold && mISDNport->l2link<1) {
634 trace_header("CHANNEL SELECTION (port's layer 2 is down, skipping)", DIRECTION_NONE);
635 add_trace("port", NULL, "%d", ifport->portnum);
636 add_trace("position", NULL, "%d", index);
641 /* check for channel form selection list */
643 selchannel = ifport->out_channel;
645 switch(selchannel->channel) {
646 case CHANNEL_FREE: /* free channel */
647 if (mISDNport->b_reserved >= mISDNport->b_num)
648 break; /* all channel in use or reserverd */
651 while(i < mISDNport->b_num) {
652 if (mISDNport->b_port[i] == NULL) {
653 *channel = i+1+(i>=15);
654 trace_header("CHANNEL SELECTION (selecting free channel)", DIRECTION_NONE);
655 add_trace("port", NULL, "%d", ifport->portnum);
656 add_trace("position", NULL, "%d", index);
657 add_trace("channel", NULL, "%d", *channel);
665 trace_header("CHANNEL SELECTION (no channel is 'free')", DIRECTION_NONE);
666 add_trace("port", NULL, "%d", ifport->portnum);
667 add_trace("position", NULL, "%d", index);
671 case CHANNEL_ANY: /* don't ask for channel */
672 if (mISDNport->b_reserved >= mISDNport->b_num) {
673 trace_header("CHANNEL SELECTION (cannot ask for 'any' channel, all reserved)", DIRECTION_NONE);
674 add_trace("port", NULL, "%d", ifport->portnum);
675 add_trace("position", NULL, "%d", index);
676 add_trace("total", NULL, "%d", mISDNport->b_num);
677 add_trace("reserved", NULL, "%d", mISDNport->b_reserved);
679 break; /* all channel in use or reserverd */
681 trace_header("CHANNEL SELECTION (using 'any' channel)", DIRECTION_NONE);
682 add_trace("port", NULL, "%d", ifport->portnum);
683 add_trace("position", NULL, "%d", index);
685 *channel = CHANNEL_ANY;
688 case CHANNEL_NO: /* call waiting */
689 trace_header("CHANNEL SELECTION (using 'no' channel, call-waiting)", DIRECTION_NONE);
690 add_trace("port", NULL, "%d", ifport->portnum);
691 add_trace("position", NULL, "%d", index);
693 *channel = CHANNEL_NO;
697 if (selchannel->channel<1 || selchannel->channel==16) {
698 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
699 add_trace("port", NULL, "%d", ifport->portnum);
700 add_trace("position", NULL, "%d", index);
701 add_trace("channel", NULL, "%d", selchannel->channel);
703 break; /* invalid channels */
705 i = selchannel->channel-1-(selchannel->channel>=17);
706 if (i >= mISDNport->b_num) {
707 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
708 add_trace("port", NULL, "%d", ifport->portnum);
709 add_trace("position", NULL, "%d", index);
710 add_trace("channel", NULL, "%d", selchannel->channel);
711 add_trace("channels", NULL, "%d", mISDNport->b_num);
713 break; /* channel not in port */
715 if (mISDNport->b_port[i] == NULL) {
716 *channel = selchannel->channel;
717 trace_header("CHANNEL SELECTION (selecting given channel)", DIRECTION_NONE);
718 add_trace("port", NULL, "%d", ifport->portnum);
719 add_trace("position", NULL, "%d", index);
720 add_trace("channel", NULL, "%d", *channel);
727 break; /* found channel */
728 selchannel = selchannel->next;
731 /* if channel was found, return mISDNport and channel */
733 /* setting next port to start next time */
734 if (interface->hunt == HUNT_ROUNDROBIN) {
738 interface->hunt_next = index;
744 trace_header("CHANNEL SELECTION (skipping, no channel found)", DIRECTION_NONE);
745 add_trace("port", NULL, "%d", ifport->portnum);
746 add_trace("position", NULL, "%d", index);
750 /* go next port, until all ports are checked */
752 ifport = ifport->next;
755 ifport = interface->ifport;
757 if (ifport != ifport_start)
761 interface = interface->next;
765 return(NULL); /* no port found */
768 /* outgoing setup to port(s)
769 * ports will be created and a setup is sent if everything is ok. otherwhise
770 * the endpoint is destroyed.
772 void EndpointAppPBX::out_setup(void)
774 struct dialing_info dialinginfo;
776 struct port_list *portlist;
777 struct lcr_msg *message;
779 int cause = CAUSE_RESSOURCEUNAVAIL;
782 struct mISDNport *mISDNport;
785 class EndpointAppPBX *atemp;
786 // char allowed_ports[256];
788 char ifname[sizeof(e_ext.interfaces)],
790 struct port_settings port_settings;
793 int mode = B_MODE_TRANSPARENT;
795 /* set bchannel mode */
796 mode = e_capainfo.source_mode;
798 /* create settings for creating port */
799 memset(&port_settings, 0, sizeof(port_settings));
801 SCPY(port_settings.tones_dir, e_ext.tones_dir);
803 SCPY(port_settings.tones_dir, options.tones_dir);
804 port_settings.no_seconds = e_ext.no_seconds;
806 /* 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 */
808 /* check what dialinginfo.itype we got */
809 switch(e_dialinginfo.itype) {
810 /* *********************** call to extension or vbox */
811 case INFO_ITYPE_ISDN_EXTENSION:
812 /* check if we deny incoming calls when we use an extension */
813 if (e_ext.noknocking) {
814 atemp = apppbx_first;
817 if (!strcmp(atemp->e_ext.number, e_ext.number))
822 PERROR("EPOINT(%d) noknocking and currently a call\n", ea_endpoint->ep_serial);
823 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYSPE_ join, port */
824 return; /* must exit here */
827 /* FALL THROUGH !!!! */
828 case INFO_ITYPE_VBOX:
829 /* get dialed extension's info */
830 // SCPY(exten, e_dialinginfo.id);
831 // if (strchr(exten, ','))
832 // *strchr(exten, ',') = '\0';
833 // if (!read_extension(&e_ext, exten))
834 if (!read_extension(&e_ext, e_dialinginfo.id)) {
835 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) extension %s not configured\n", ea_endpoint->ep_serial, e_dialinginfo.id);
836 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
837 return; /* must exit here */
840 if (e_dialinginfo.itype == INFO_ITYPE_VBOX) {
841 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing directly to VBOX\n", ea_endpoint->ep_serial);
846 /* string from unconditional call forward (cfu) */
849 /* present to forwarded party */
850 if (e_ext.anon_ignore && e_callerinfo.id[0]) {
851 e_callerinfo.present = INFO_PRESENT_ALLOWED;
853 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
857 /* string from busy call forward (cfb) */
860 class EndpointAppPBX *checkapp = apppbx_first;
862 if (checkapp != this) { /* any other endpoint except our own */
863 if (!strcmp(checkapp->e_ext.number, e_ext.number)) {
864 /* present to forwarded party */
865 if (e_ext.anon_ignore && e_callerinfo.id[0]) {
866 e_callerinfo.present = INFO_PRESENT_ALLOWED;
868 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
872 checkapp = checkapp->next;
876 /* string from no-response call forward (cfnr) */
879 /* when cfnr is done, out_setup() will setup the call */
881 /* present to forwarded party */
882 if (e_ext.anon_ignore && e_callerinfo.id[0]) {
883 e_callerinfo.present = INFO_PRESENT_ALLOWED;
887 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH)) {
888 e_cfnr_release = now + e_ext.cfnr_delay;
889 e_cfnr_call = now + e_ext.cfnr_delay + 1; /* call one second after release */
890 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);
894 /* call to all internal interfaces */
895 p = e_ext.interfaces;
896 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) generating multiple joins for extension %s to interfaces %s\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
899 while(*p!=',' && *p!='\0')
904 /* found interface */
905 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
906 /* hunt for mISDNport and create Port */
907 mISDNport = hunt_port(ifname, &channel);
909 trace_header("INTERFACE (not found or busy)", DIRECTION_NONE);
910 add_trace("interface", NULL, "%s", ifname);
914 /* creating INTERNAL port */
915 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
917 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);
920 port = new Pgsm(PORT_TYPE_GSM_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
925 FATAL("No memory for Port instance\n");
926 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
927 memset(&dialinginfo, 0, sizeof(dialinginfo));
928 SCPY(dialinginfo.id, e_dialinginfo.id);
929 dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
930 dialinginfo.ntype = e_dialinginfo.ntype;
931 /* create port_list relation */
932 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
934 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
936 goto check_anycall_intern;
939 if (e_callerinfo.id[0] && e_ext.display_name) {
940 dirname = parse_directory(e_callerinfo.id, e_callerinfo.ntype);
942 SCPY(e_callerinfo.name, dirname);
944 // dss1 = (class Pdss1 *)port;
946 //printf("INTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
947 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
948 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
949 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
950 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
951 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
952 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
953 //terminal if (e_dialinginfo.id)
954 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
955 /* handle restricted caller ids */
956 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);
957 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);
958 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);
959 /* display callerid if desired for extension */
960 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));
961 //printf("\n\ndisplay = %s\n\n\n",message->param.setup.callerinfo.display);
962 /* use cnip, if enabld */
963 // if (!e_ext.centrex)
964 // message->param.setup.callerinfo.name[0] = '\0';
965 /* screen clip if prefix is required */
966 if (message->param.setup.callerinfo.id[0] && e_ext.clip_prefix[0]) {
967 SCPY(message->param.setup.callerinfo.id, e_ext.clip_prefix);
968 SCAT(message->param.setup.callerinfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype, options.national, options.international));
969 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
971 if (message->param.setup.callerinfo.id2[0] && e_ext.clip_prefix[0]) {
972 SCPY(message->param.setup.callerinfo.id2, e_ext.clip_prefix);
973 SCAT(message->param.setup.callerinfo.id2, numberrize_callerinfo(e_callerinfo.id2,e_callerinfo.ntype2, options.national, options.international));
974 message->param.setup.callerinfo.ntype2 = INFO_NTYPE_UNKNOWN;
976 /* use internal caller id */
977 if (e_callerinfo.extension[0] && (message->param.setup.callerinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore)) {
978 SCPY(message->param.setup.callerinfo.id, e_callerinfo.extension);
979 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
980 message->param.setup.callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
982 message_put(message);
983 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
987 /* string from parallel call forward (cfp) */
990 if (e_ext.anon_ignore && e_callerinfo.id[0]) {
991 e_callerinfo.present = INFO_PRESENT_ALLOWED;
992 e_callerinfo.present2 = INFO_PRESENT_ALLOWED;
996 vbox_only: /* entry point for answering machine only */
997 cfu_only: /* entry point for cfu */
998 cfb_only: /* entry point for cfb */
999 cfnr_only: /* entry point for cfnr */
1000 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call extension %s for external destiantion(s) '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
1004 /* only if vbox should be dialed, and terminal is given */
1005 if (!strcmp(p, "vbox") && e_ext.number[0]) {
1006 /* go to the end of p */
1009 /* answering vbox call */
1010 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) answering machine\n", ea_endpoint->ep_serial);
1012 if (!(port = new VBoxPort(PORT_TYPE_VBOX_OUT, &port_settings)))
1013 FATAL("No memory for VBOX Port instance\n");
1014 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocated port %s\n", ea_endpoint->ep_serial, port->p_name);
1015 UCPY(cfp, e_ext.number); /* cfp or any other direct forward/vbox */
1018 while(*p!=',' && *p!='\0')
1023 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cfp external %s\n", ea_endpoint->ep_serial, cfp);
1024 /* hunt for mISDNport and create Port */
1025 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1027 /* creating EXTERNAL port*/
1028 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1029 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);
1031 FATAL("No memory for Port instance\n");
1032 earlyb = mISDNport->earlyb;
1035 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1036 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1041 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port found or created, which is idle.\n", ea_endpoint->ep_serial);
1042 goto check_anycall_intern;
1044 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found or created port %s\n", ea_endpoint->ep_serial, port->p_name);
1045 memset(&dialinginfo, 0, sizeof(dialinginfo));
1046 SCPY(dialinginfo.id, cfp);
1047 dialinginfo.itype = INFO_ITYPE_ISDN;
1048 dialinginfo.ntype = e_dialinginfo.ntype;
1049 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
1051 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1053 goto check_anycall_intern;
1055 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1056 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1057 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1058 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1059 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1060 /* if clip is hidden */
1061 if (e_ext.clip==CLIP_HIDE && port->p_type!=PORT_TYPE_VBOX_OUT) {
1062 SCPY(message->param.setup.callerinfo.id, e_ext.callerid);
1063 SCPY(message->param.setup.callerinfo.extension, e_ext.number);
1064 message->param.setup.callerinfo.ntype = e_ext.callerid_type;
1065 message->param.setup.callerinfo.present = e_ext.callerid_present;
1066 message->param.setup.callerinfo.ntype = INFO_NTYPE_NOTPRESENT;
1068 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1069 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1070 //terminal if (e_dialinginfo.id)
1071 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1072 /* handle restricted caller ids */
1073 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);
1074 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);
1075 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);
1076 /* display callerid if desired for extension */
1077 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));
1078 message_put(message);
1079 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1083 check_anycall_intern:
1084 /* now we have all ports created */
1086 trace_header("INTERFACE (no extension's interface)", DIRECTION_NONE);
1088 if (!ea_endpoint->ep_join_id)
1090 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1091 return; /* must exit here */
1095 /* *********************** external call */
1097 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id);
1098 /* call to extenal interfaces */
1099 p = e_dialinginfo.id;
1102 while(*p!=',' && *p!='\0')
1103 SCCAT(number, *p++);
1107 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");
1108 /* hunt for mISDNport and create Port */
1109 /* hunt for mISDNport and create Port */
1110 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1112 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1113 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1115 goto check_anycall_extern;
1117 /* creating EXTERNAL port*/
1118 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1119 if (!mISDNport->gsm)
1120 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);
1123 port = new Pgsm(PORT_TYPE_GSM_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
1128 FATAL("No memory for Port instance\n");
1129 earlyb = mISDNport->earlyb;
1130 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
1131 memset(&dialinginfo, 0, sizeof(dialinginfo));
1132 SCPY(dialinginfo.id, number);
1133 dialinginfo.itype = INFO_ITYPE_ISDN;
1134 dialinginfo.ntype = e_dialinginfo.ntype;
1135 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
1137 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1139 goto check_anycall_extern;
1141 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1142 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1143 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1144 SCPY(message->param.setup.dialinginfo.id, number);
1145 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1146 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1147 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1148 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1149 //terminal if (e_dialinginfo.id)
1150 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1151 /* handle restricted caller ids */
1152 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);
1153 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);
1154 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);
1155 /* display callerid if desired for extension */
1156 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));
1157 message_put(message);
1158 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1162 check_anycall_extern:
1163 /* now we have all ports created */
1165 trace_header("INTERFACE (no free ports found)", DIRECTION_NONE);
1167 if (!ea_endpoint->ep_join_id)
1169 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1170 return; /* must exit here */
1178 /* handler for endpoint
1182 int EndpointAppPBX::handler(void)
1184 if (e_crypt_state!=CM_ST_NULL) {
1188 /* process answering machine (play) handling */
1190 if (e_action->index == ACTION_VBOX_PLAY)
1193 /* process action timeout */
1194 if (e_action_timeout)
1195 if (now_d >= e_action_timeout) {
1196 if (e_state!=EPOINT_STATE_CONNECT) {
1198 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current action timed out.\n", ea_endpoint->ep_serial);
1199 e_multipoint_cause = 0;
1200 e_multipoint_location = 0;
1201 new_state(EPOINT_STATE_IN_OVERLAP);
1204 return(1); /* we must exit, because our endpoint might be gone */
1206 e_action_timeout = 0;
1209 /* process action timeout */
1210 if (e_match_timeout)
1211 if (now_d >= e_match_timeout) {
1213 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we got a match timeout.\n", ea_endpoint->ep_serial);
1215 return(1); /* we must exit, because our endpoint might be gone */
1220 /* process redialing (epoint redials to port) */
1222 if (now_d >= e_redial) {
1224 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial.\n", ea_endpoint->ep_serial);
1226 new_state(EPOINT_STATE_OUT_SETUP);
1227 /* call special setup routine */
1234 /* process powerdialing (epoint redials to epoint) */
1235 if (e_powerdialing > 0) {
1236 if (now_d >= e_powerdialing) {
1237 e_powerdialing = -1; /* leave power dialing on */
1238 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial of powerdial.\n", ea_endpoint->ep_serial);
1241 e_ruleset = ruleset_main;
1243 e_rule = e_ruleset->rule_first;
1245 new_state(EPOINT_STATE_IN_OVERLAP);
1251 /* process call forward no response */
1252 if (e_cfnr_release) {
1253 struct port_list *portlist;
1254 struct lcr_msg *message;
1256 if (now >= e_cfnr_release) {
1257 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-no-response time has expired, hanging up.\n", ea_endpoint->ep_serial);
1260 /* release all ports */
1261 while((portlist = ea_endpoint->ep_portlist)) {
1262 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1263 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
1264 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1265 message_put(message);
1266 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1267 ea_endpoint->free_portlist(portlist);
1270 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1271 message->param.audiopath = 0;
1272 message_put(message);
1273 /* indicate no patterns */
1274 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1275 message_put(message);
1276 /* set setup state, since we have no response from the new join */
1277 new_state(EPOINT_STATE_OUT_SETUP);
1281 if (now >= e_cfnr_call) {
1282 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-busy time has expired, calling the forwarded number: %s.\n", ea_endpoint->ep_serial, e_ext.cfnr);
1288 /* handle connection to user */
1289 if (e_state == EPOINT_STATE_IDLE) {
1290 /* epoint is idle, check callback */
1292 if (now_d >= e_callback) {
1293 e_callback = 0; /* done with callback */
1294 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting callback.\n", ea_endpoint->ep_serial);
1295 new_state(EPOINT_STATE_OUT_SETUP);
1301 /* check for password timeout */
1303 if (e_action->index==ACTION_PASSWORD || e_action->index==ACTION_PASSWORD_WRITE) {
1304 struct port_list *portlist;
1306 if (now >= e_password_timeout) {
1307 e_ruleset = ruleset_main;
1309 e_rule = e_ruleset->rule_first;
1311 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) password timeout %s\n", ea_endpoint->ep_serial, e_extdialing);
1312 trace_header("PASSWORD timeout", DIRECTION_NONE);
1314 e_connectedmode = 0;
1316 new_state(EPOINT_STATE_OUT_DISCONNECT);
1317 portlist = ea_endpoint->ep_portlist;
1319 message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
1320 set_tone(portlist, "cause_10");
1330 /* doing a hookflash */
1331 void EndpointAppPBX::hookflash(void)
1335 /* be sure that we are active */
1337 e_tx_state = NOTIFY_STATE_ACTIVE;
1339 trace_header("HOOKFLASH DTMF", DIRECTION_NONE);
1341 if (ea_endpoint->ep_use > 1) {
1342 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot hooflash while child process is running.\n", ea_endpoint->ep_serial);
1345 /* dialtone after pressing the hash key */
1346 process_hangup(e_join_cause, e_join_location);
1347 e_multipoint_cause = 0;
1348 e_multipoint_location = 0;
1349 port = find_port_id(ea_endpoint->ep_portlist->port_id);
1351 port->set_echotest(0);
1353 if (ea_endpoint->ep_join_id) {
1354 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1356 e_ruleset = ruleset_main;
1358 e_rule = e_ruleset->rule_first;
1360 new_state(EPOINT_STATE_IN_OVERLAP);
1361 e_connectedmode = 1;
1362 SCPY(e_dialinginfo.id, e_ext.prefix);
1363 e_extdialing = e_dialinginfo.id;
1365 if (e_dialinginfo.id[0]) {
1366 set_tone(ea_endpoint->ep_portlist, "dialing");
1369 set_tone(ea_endpoint->ep_portlist, "dialpbx");
1376 /* messages from port
1378 /* port MESSAGE_SETUP */
1379 void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, union parameter *param)
1381 struct lcr_msg *message;
1383 int writeext; /* flags need to write extension after modification */
1385 struct interface *interface;
1387 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1389 portlist->port_type = param->setup.port_type;
1390 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
1391 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
1392 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
1393 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
1394 // e_dtmf = param->setup.dtmf;
1395 /* screen incoming caller id */
1396 interface = interface_first;
1398 if (!strcmp(e_callerinfo.interface, interface->name)) {
1401 interface = interface->next;
1404 do_screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface);
1405 do_screen(0, e_callerinfo.id2, sizeof(e_callerinfo.id2), &e_callerinfo.ntype2, &e_callerinfo.present2, interface);
1408 /* process extension */
1409 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION) {
1410 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is extension\n", ea_endpoint->ep_serial);
1411 /* port makes call from extension */
1412 SCPY(e_callerinfo.extension, e_callerinfo.id);
1413 SCPY(e_ext.number, e_callerinfo.extension);
1414 SCPY(e_extension_interface, e_callerinfo.interface);
1416 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is external or voip\n", ea_endpoint->ep_serial);
1419 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION) {
1420 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1422 /* get extension's info about caller */
1423 if (!read_extension(&e_ext, e_ext.number)) {
1424 /* extension doesn't exist */
1425 trace_header("EXTENSION (not created)", DIRECTION_IN);
1426 add_trace("extension", NULL, "%s", e_ext.number);
1428 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
1429 new_state(EPOINT_STATE_OUT_DISCONNECT);
1430 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
1431 e_ext.number[0] = '\0'; /* no terminal */
1436 /* put prefix (next) in front of e_dialinginfo.id */
1437 if (e_ext.next[0]) {
1438 SPRINT(buffer, "%s%s", e_ext.next, e_dialinginfo.id);
1439 SCPY(e_dialinginfo.id, buffer);
1440 e_ext.next[0] = '\0';
1442 } else if (e_ext.prefix[0]) {
1443 SPRINT(buffer, "%s%s", e_ext.prefix, e_dialinginfo.id);
1444 SCPY(e_dialinginfo.id, buffer);
1447 /* screen caller id by extension's config */
1448 e_callerinfo.screen = INFO_SCREEN_NETWORK;
1450 SCPY(e_callerinfo.name, e_ext.name);
1451 /* use caller id (or if exist: id_next_call) for this call */
1452 if (e_ext.id_next_call_present >= 0) {
1453 SCPY(e_callerinfo.id, e_ext.id_next_call);
1454 /* if we restrict the pesentation */
1455 if (e_ext.id_next_call_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1456 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1457 else e_callerinfo.present = e_ext.id_next_call_present;
1458 e_callerinfo.ntype = e_ext.id_next_call_type;
1459 e_ext.id_next_call_present = -1;
1462 SCPY(e_callerinfo.id, e_ext.callerid);
1463 /* if we restrict the pesentation */
1464 if (e_ext.callerid_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1465 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1466 else e_callerinfo.present = e_ext.callerid_present;
1467 e_callerinfo.ntype = e_ext.callerid_type;
1469 e_callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
1471 /* extension is written */
1473 write_extension(&e_ext, e_ext.number);
1475 /* set volume of rx and tx */
1476 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1477 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0) {
1478 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
1479 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
1480 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
1481 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
1482 message_put(message);
1485 /* start recording if enabled */
1486 if (e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO)) {
1487 /* check if we are a terminal */
1488 if (e_ext.number[0] == '\0')
1489 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
1491 port = find_port_id(portlist->port_id);
1493 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
1497 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from external port\n", ea_endpoint->ep_serial);
1498 /* no terminal identification */
1499 e_ext.number[0] = '\0';
1500 e_extension_interface[0] = '\0';
1501 memset(&e_ext, 0, sizeof(e_ext));
1502 e_ext.rights = 4; /* right to dial internat */
1506 e_ruleset = ruleset_main;
1508 e_rule = e_ruleset->rule_first;
1510 e_extdialing = e_dialinginfo.id;
1511 new_state(EPOINT_STATE_IN_SETUP);
1512 if (e_dialinginfo.id[0]) {
1513 set_tone(portlist, "dialing");
1515 if (e_ext.number[0])
1516 set_tone(portlist, "dialpbx");
1518 set_tone(portlist, "dialtone");
1521 if (e_state == EPOINT_STATE_IN_SETUP) {
1522 /* request MORE info, if not already at higher state */
1523 new_state(EPOINT_STATE_IN_OVERLAP);
1524 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_OVERLAP);
1525 message_put(message);
1526 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1530 /* port MESSAGE_INFORMATION */
1531 void EndpointAppPBX::port_information(struct port_list *portlist, int message_type, union parameter *param)
1533 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1535 /* ignore information message without digit information */
1536 if (!param->information.id[0])
1541 /* turn off dtmf detection, in case dtmf is sent with keypad information */
1543 trace_header("DTMF (disabling due to keypad)", DIRECTION_IN);
1548 /* if vbox_play is done, the information are just used as they come */
1550 if (e_action->index == ACTION_VBOX_PLAY) {
1551 /* concat dialing string */
1552 SCAT(e_dialinginfo.id, param->information.id);
1557 /* keypad when disconnect but in connected mode */
1558 if (e_state==EPOINT_STATE_OUT_DISCONNECT && e_connectedmode) {
1559 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received after disconnect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1560 /* processing keypad function */
1561 if (param->information.id[0] == '0') {
1567 /* keypad when connected */
1568 if (e_state == EPOINT_STATE_CONNECT || e_state == EPOINT_STATE_IN_ALERTING) {
1569 if (e_ext.keypad || e_enablekeypad) {
1570 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1571 /* processing keypad function */
1572 if (param->information.id[0] == '0') {
1575 if (param->information.id[0])
1576 keypad_function(param->information.id[0]);
1578 if (e_ext.number[0])
1579 trace_header("KEYPAD (not enabled by extension's settings)", DIRECTION_IN);
1581 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1586 if (e_state != EPOINT_STATE_IN_OVERLAP) {
1587 if (e_ext.number[0])
1588 trace_header("KEYPAD (ignored, not connected and not dialing)", DIRECTION_IN);
1590 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1594 if (!param->information.id[0])
1596 if (e_dialinginfo.id[0]=='\0' && !e_action) {
1597 set_tone(portlist, "dialing");
1600 if (e_action->index==ACTION_OUTDIAL
1601 || e_action->index==ACTION_EXTERNAL
1602 || e_action->index==ACTION_REMOTE) {
1604 set_tone(portlist, "dialing");
1605 else if (!e_extdialing[0])
1606 set_tone(portlist, "dialing");
1608 /* concat dialing string */
1609 SCAT(e_dialinginfo.id, param->information.id);
1613 /* port MESSAGE_DTMF */
1614 void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
1616 /* only if dtmf detection is enabled */
1618 trace_header("DTMF (disabled)", DIRECTION_IN);
1622 trace_header("DTMF", DIRECTION_IN);
1623 add_trace("digit", NULL, "%c", param->dtmf);
1627 NOTE: vbox is now handled due to overlap state
1628 /* if vbox_play is done, the dtmf digits are just used as they come */
1630 if (e_action->index == ACTION_VBOX_PLAY) {
1631 /* concat dialing string */
1632 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id)) {
1633 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1634 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1637 /* continue to process *X# sequences */
1641 /* check for *X# sequence */
1642 if (e_state == EPOINT_STATE_CONNECT || e_state == EPOINT_STATE_IN_ALERTING) {
1643 if (e_dtmf_time+3 < now) {
1644 /* the last digit was too far in the past to be a sequence */
1645 if (param->dtmf == '*')
1646 /* only start is allowed in the sequence */
1651 /* we have a sequence of digits, see what we got */
1652 if (param->dtmf == '*')
1654 else if (param->dtmf>='0' && param->dtmf<='9') {
1655 /* we need to have a star before we receive the digit of the sequence */
1656 if (e_dtmf_last == '*')
1657 e_dtmf_last = param->dtmf;
1658 } else if (param->dtmf == '#') {
1660 if (e_dtmf_last>='0' && e_dtmf_last<='9') {
1661 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf sequence *%c# detected.\n", ea_endpoint->ep_serial, e_dtmf_last);
1662 if (e_dtmf_last == '0') {
1666 /* processing keypad function */
1668 keypad_function(e_dtmf_last);
1674 /* set last time of dtmf */
1679 /* check for ## hookflash during dialing */
1681 if (e_action->index==ACTION_PASSWORD
1682 || e_action->index==ACTION_PASSWORD_WRITE)
1684 if (param->dtmf=='#') { /* current digit is '#' */
1685 if (e_state==EPOINT_STATE_IN_DISCONNECT
1686 || (e_state!=EPOINT_STATE_CONNECT && e_dtmf_time+3>=now && e_dtmf_last=='#')) { /* when disconnected, just #. when dialing, ##. */
1700 /* dialing using dtmf digit */
1701 if (e_state==EPOINT_STATE_IN_OVERLAP){ // && e_state==e_connectedmode)
1702 if (e_dialinginfo.id[0]=='\0' && !e_action) {
1703 set_tone(portlist, "dialing");
1705 /* concat dialing string */
1706 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id)) {
1707 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1708 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1714 /* port MESSAGE_CRYPT */
1715 void EndpointAppPBX::port_crypt(struct port_list *portlist, int message_type, union parameter *param)
1717 /* send crypt response to cryptman */
1718 if (param->crypt.type == CR_MESSAGE_IND)
1719 cryptman_msg2man(param->crypt.data, param->crypt.len);
1721 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
1724 /* port MESSAGE_OVERLAP */
1725 void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, union parameter *param)
1727 struct lcr_msg *message;
1729 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1731 /* signal to call tool */
1732 admin_call_response(e_adminid, ADMIN_CALL_SETUP_ACK, "", 0, 0, 0);
1734 if (e_dialing_queue[0] && portlist) {
1735 /* send what we have not dialed yet, because we had no setup complete */
1736 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing pending digits: '%s'\n", ea_endpoint->ep_serial, e_dialing_queue);
1737 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
1738 SCPY(message->param.information.id, e_dialing_queue);
1739 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
1740 message_put(message);
1741 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
1742 e_dialing_queue[0] = '\0';
1744 /* check if pattern is available */
1745 if (!ea_endpoint->ep_portlist->next && portlist->early_b) { /* one port_list relation and tones available */
1746 /* indicate patterns */
1747 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1748 message_put(message);
1750 /* connect audio, if not already */
1751 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1752 message->param.audiopath = 1;
1753 message_put(message);
1755 /* indicate no patterns */
1756 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1757 message_put(message);
1759 /* disconnect audio, if not already */
1760 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1761 message->param.audiopath = 0;
1762 message_put(message);
1764 new_state(EPOINT_STATE_OUT_OVERLAP);
1765 /* if we are in a join */
1766 if (ea_endpoint->ep_join_id) {
1767 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1768 memcpy(&message->param, param, sizeof(union parameter));
1769 message_put(message);
1773 /* port MESSAGE_PROCEEDING */
1774 void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_type, union parameter *param)
1776 struct lcr_msg *message;
1778 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1780 /* signal to call tool */
1781 admin_call_response(e_adminid, ADMIN_CALL_PROCEEDING, "", 0, 0, 0);
1783 e_state = EPOINT_STATE_OUT_PROCEEDING;
1784 /* check if pattern is availatle */
1785 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) { /* one port_list relation and tones available */
1786 /* indicate patterns */
1787 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1788 message_put(message);
1790 /* connect audio, if not already */
1791 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1792 message->param.audiopath = 1;
1793 message_put(message);
1795 /* indicate no patterns */
1796 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1797 message_put(message);
1799 /* disconnect audio, if not already */
1800 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1801 message->param.audiopath = 0;
1802 message_put(message);
1804 /* if we are in a call */
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_ALERTING */
1813 void EndpointAppPBX::port_alerting(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_ALERTING, "", 0, 0, 0);
1823 // set_tone(portlist, "hold");
1825 new_state(EPOINT_STATE_OUT_ALERTING);
1826 /* check if pattern is available */
1827 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) { /* one port_list relation and tones available */
1828 /* indicate patterns */
1829 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1830 message_put(message);
1832 /* connect audio, if not already */
1833 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1834 message->param.audiopath = 1;
1835 message_put(message);
1837 /* indicate no patterns */
1838 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1839 message_put(message);
1841 /* disconnect audio, if not already */
1842 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1843 message->param.audiopath = 0;
1844 message_put(message);
1846 /* if we are in a call */
1847 if (ea_endpoint->ep_join_id) {
1848 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1849 memcpy(&message->param, param, sizeof(union parameter));
1850 message_put(message);
1854 /* port MESSAGE_CONNECT */
1855 void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, union parameter *param)
1857 struct lcr_msg *message;
1859 unsigned int port_id = portlist->port_id;
1860 struct port_list *tportlist;
1862 struct interface *interface;
1864 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1866 /* signal to call tool */
1867 admin_call_response(e_adminid, ADMIN_CALL_CONNECT, numberrize_callerinfo(param->connectinfo.id,param->connectinfo.ntype, options.national, options.international), 0, 0, 0);
1869 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_connectinfo));
1870 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (start)\n", ea_endpoint->ep_serial);
1871 while(ea_endpoint->ep_portlist->next) { /* as long as we have at least two ports */
1872 tportlist = ea_endpoint->ep_portlist;
1873 if (tportlist->port_id == port_id) /* if the first portlist is the calling one, the second must be a different one */
1874 tportlist = tportlist->next;
1875 if (tportlist->port_id == port_id)
1876 FATAL("EPOINT(%d) this should not happen since the portlist list must not have two links to the same port - exitting.\n");
1877 message = message_create(ea_endpoint->ep_serial, tportlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1878 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
1879 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1880 message_put(message);
1881 logmessage(message->type, &message->param, tportlist->port_id, DIRECTION_OUT);
1882 ea_endpoint->free_portlist(tportlist);
1884 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (end)\n", ea_endpoint->ep_serial);
1888 /* screen incoming connected id */
1889 interface = interface_first;
1891 if (!strcmp(e_connectinfo.interface, interface->name)) {
1894 interface = interface->next;
1897 do_screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface);
1899 /* screen connected name */
1901 SCPY(e_connectinfo.name, e_ext.name);
1903 /* add internal id to colp */
1904 SCPY(e_connectinfo.extension, e_ext.number);
1906 /* we store the connected port number */
1907 SCPY(e_extension_interface, e_connectinfo.interface);
1909 /* for internal and am calls, we get the extension's id */
1910 if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE) {
1911 SCPY(e_connectinfo.id, e_ext.callerid);
1912 SCPY(e_connectinfo.extension, e_ext.number);
1913 e_connectinfo.itype = INFO_ITYPE_ISDN_EXTENSION;
1914 e_connectinfo.ntype = e_ext.callerid_type;
1915 e_connectinfo.present = e_ext.callerid_present;
1917 if (portlist->port_type==PORT_TYPE_VBOX_OUT) {
1918 e_connectinfo.itype = INFO_ITYPE_VBOX;
1919 e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
1922 new_state(EPOINT_STATE_CONNECT);
1924 /* set volume of rx and tx */
1925 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0) {
1926 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
1927 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
1928 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
1929 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
1930 message_put(message);
1933 e_cfnr_call = e_cfnr_release = 0;
1934 if (e_ext.number[0])
1935 e_dtmf = 1; /* allow dtmf */
1938 /* other calls with no caller id (or not available for the extension) and force colp */
1939 if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE) {
1940 e_connectinfo.ntype = INFO_NTYPE_NOTPRESENT;
1941 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 */
1942 port = find_port_id(portlist->port_id);
1944 SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.id, &e_connectinfo.ntype, options.national, options.international));
1945 e_connectinfo.present = INFO_PRESENT_ALLOWED;
1950 /* send connect to join */
1951 if (ea_endpoint->ep_join_id) {
1952 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1953 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
1954 message_put(message);
1956 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1957 message->param.audiopath = 1;
1958 message_put(message);
1959 } else if (!e_adminid) {
1961 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have a callback, so we create a call with cbcaller: \"%s\".\n", ea_endpoint->ep_serial, e_cbcaller);
1962 SCPY(e_ext.number, e_cbcaller);
1963 new_state(EPOINT_STATE_IN_OVERLAP);
1964 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) callback from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1966 /* get extension's info about terminal */
1967 if (!read_extension(&e_ext, e_ext.number)) {
1968 /* extension doesn't exist */
1969 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1970 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
1971 new_state(EPOINT_STATE_OUT_DISCONNECT);
1972 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
1976 /* put prefix in front of e_cbdialing */
1977 SPRINT(buffer, "%s%s", e_ext.prefix, e_cbdialing);
1978 SCPY(e_dialinginfo.id, buffer);
1979 e_dialinginfo.itype = INFO_ITYPE_ISDN;
1980 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
1982 /* use caller id (or if exist: id_next_call) for this call */
1983 e_callerinfo.screen = INFO_SCREEN_NETWORK;
1984 SCPY(e_callerinfo.extension, e_ext.number);
1985 if (e_ext.id_next_call_present >= 0) {
1986 SCPY(e_callerinfo.id, e_ext.id_next_call);
1987 e_callerinfo.present = e_ext.id_next_call_present;
1988 e_callerinfo.ntype = e_ext.id_next_call_type;
1989 e_ext.id_next_call_present = -1;
1990 /* extension is written */
1991 write_extension(&e_ext, e_ext.number);
1993 SCPY(e_callerinfo.id, e_ext.callerid);
1994 e_callerinfo.present = e_ext.callerid_present;
1995 e_callerinfo.ntype = e_ext.callerid_type;
1997 e_callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
1999 e_connectedmode = 1; /* dtmf-hangup & disconnect prevention */
2002 /* check if caller id is NOT authenticated */
2003 if (!parse_callbackauth(e_ext.number, &e_callbackinfo)) {
2004 /* make call state to enter password */
2005 new_state(EPOINT_STATE_IN_OVERLAP);
2006 e_action = &action_password_write;
2007 e_match_timeout = 0;
2008 e_match_to_action = NULL;
2009 e_dialinginfo.id[0] = '\0';
2010 e_extdialing = strchr(e_dialinginfo.id, '\0');
2011 e_password_timeout = now+20;
2014 /* incoming call (callback) */
2015 e_ruleset = ruleset_main;
2017 e_rule = e_ruleset->rule_first;
2019 e_extdialing = e_dialinginfo.id;
2020 if (e_dialinginfo.id[0]) {
2021 set_tone(portlist, "dialing");
2024 set_tone(portlist, "dialpbx");
2027 } else { /* testcall */
2028 set_tone(portlist, "hold");
2031 /* start recording if enabled, not when answering machine answers */
2032 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)) {
2033 /* check if we are a terminal */
2034 if (e_ext.number[0] == '\0')
2035 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
2037 port = find_port_id(portlist->port_id);
2039 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
2044 /* port MESSAGE_DISCONNECT MESSAGE_RELEASE */
2045 void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
2047 struct lcr_msg *message;
2049 unsigned int port_id = portlist->port_id;
2053 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2055 /* signal to call tool */
2056 admin_call_response(e_adminid, (message_type==MESSAGE_DISCONNECT)?ADMIN_CALL_DISCONNECT:ADMIN_CALL_RELEASE, "", param->disconnectinfo.cause, param->disconnectinfo.location, 0);
2058 //#warning does this work? only disconnect when incoming port hat not already disconnected yet?
2059 if (e_state==EPOINT_STATE_IN_DISCONNECT && message_type!=MESSAGE_RELEASE){ // || e_state==EPOINT_STATE_OUT_DISCONNECT || e_state==EPOINT_STATE_IDLE)
2060 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are already disconnected.\n", ea_endpoint->ep_serial);
2065 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);
2066 collect_cause(&e_multipoint_cause, &e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location);
2067 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new multipoint cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location);
2069 /* check if we have more than one portlist relation and we just ignore the disconnect */
2070 if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist->next) {
2071 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the disconnect was from a multipoint call. we just release that relation.\n", ea_endpoint->ep_serial);
2072 portlist = ea_endpoint->ep_portlist;
2074 if (portlist->port_id == port_id)
2076 portlist = portlist->next;
2079 FATAL("EPOINT(%d) no portlist related to the calling port.\n", ea_endpoint->ep_serial);
2080 if (message_type != MESSAGE_RELEASE) {
2081 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2082 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2083 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2084 message_put(message);
2085 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2087 ea_endpoint->free_portlist(portlist);
2088 return; /* one relation removed */
2090 if (e_state == EPOINT_STATE_CONNECT) {
2091 /* use cause from port after connect */
2092 cause = param->disconnectinfo.cause;
2093 location = param->disconnectinfo.location;
2095 /* use multipoint cause if no connect yet */
2096 if (e_multipoint_cause) {
2097 cause = e_multipoint_cause;
2098 location = e_multipoint_location;
2100 cause = CAUSE_NOUSER;
2101 location = LOCATION_PRIVATE_LOCAL;
2105 e_cfnr_call = e_cfnr_release = 0;
2107 /* process hangup */
2108 process_hangup(e_join_cause, e_join_location);
2109 e_multipoint_cause = 0;
2110 e_multipoint_location = 0;
2112 if (message_type == MESSAGE_DISCONNECT) {
2113 /* tone to disconnected end */
2114 SPRINT(buffer, "cause_%02x", cause);
2115 if (ea_endpoint->ep_portlist)
2116 set_tone(ea_endpoint->ep_portlist, buffer);
2118 new_state(EPOINT_STATE_IN_DISCONNECT);
2121 if (ea_endpoint->ep_join_id) {
2122 int haspatterns = 0;
2123 /* check if pattern is available */
2124 if (ea_endpoint->ep_portlist)
2125 if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->early_b)
2126 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
2127 && message_type != MESSAGE_RELEASE) // if we release, we are done
2130 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has patterns.\n", ea_endpoint->ep_serial);
2131 /* indicate patterns */
2132 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2133 message_put(message);
2134 /* connect audio, if not already */
2135 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2136 message->param.audiopath = 1;
2137 message_put(message);
2138 /* send disconnect */
2139 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2140 memcpy(&message->param, param, sizeof(union parameter));
2141 message_put(message);
2142 /* disable encryption if disconnected */
2143 //PERROR("REMOVE ME: state =%d, %d\n", e_crypt_state, e_crypt);
2145 cryptman_message(CI_DISCONNECT_IND, NULL, 0);
2148 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
2151 if (message_type == MESSAGE_RELEASE)
2152 ea_endpoint->free_portlist(portlist);
2153 release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, callcause, portcause */
2154 return; /* must exit here */
2157 /* port MESSAGE_TIMEOUT */
2158 void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type, union parameter *param)
2162 trace_header("TIMEOUT", DIRECTION_IN);
2163 message_type = MESSAGE_DISCONNECT;
2164 switch (param->state) {
2165 case PORT_STATE_OUT_SETUP:
2166 case PORT_STATE_OUT_OVERLAP:
2167 add_trace("state", NULL, "outgoing setup/dialing");
2169 /* no user responding */
2170 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2171 return; /* must exit here */
2173 case PORT_STATE_IN_SETUP:
2174 case PORT_STATE_IN_OVERLAP:
2175 add_trace("state", NULL, "incoming setup/dialing");
2176 param->disconnectinfo.cause = CAUSE_INVALID; /* number incomplete */
2177 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2180 case PORT_STATE_OUT_PROCEEDING:
2181 add_trace("state", NULL, "outgoing proceeding");
2183 param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
2184 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2185 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2186 return; /* must exit here */
2188 case PORT_STATE_IN_PROCEEDING:
2189 add_trace("state", NULL, "incoming proceeding");
2190 param->disconnectinfo.cause = CAUSE_NOUSER;
2191 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL; /* no user responding */
2194 case PORT_STATE_OUT_ALERTING:
2195 add_trace("state", NULL, "outgoing alerting");
2197 param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
2198 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2199 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2200 return; /* must exit here */
2202 case PORT_STATE_CONNECT:
2203 add_trace("state", NULL, "connect");
2205 param->disconnectinfo.cause = CAUSE_NORMAL; /* normal */
2206 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2207 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2208 return; /* must exit here */
2210 case PORT_STATE_IN_ALERTING:
2211 add_trace("state", NULL, "incoming alerting");
2212 param->disconnectinfo.cause = CAUSE_NOANSWER;
2213 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2216 case PORT_STATE_IN_DISCONNECT:
2217 case PORT_STATE_OUT_DISCONNECT:
2218 add_trace("state", NULL, "disconnect");
2220 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
2221 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2222 return; /* must exit here */
2225 param->disconnectinfo.cause = 31; /* normal unspecified */
2226 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2229 /* release call, disconnect isdn */
2231 new_state(EPOINT_STATE_OUT_DISCONNECT);
2232 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2233 SCPY(e_tone, cause);
2235 set_tone(portlist, cause);
2236 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2237 portlist = portlist->next;
2239 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
2242 /* port MESSAGE_NOTIFY */
2243 void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, union parameter *param)
2245 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2247 struct lcr_msg *message;
2248 const char *logtext = "";
2251 /* signal to call tool */
2252 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);
2253 if (param->notifyinfo.notify) {
2254 e_rx_state = track_notify(e_rx_state, param->notifyinfo.notify);
2257 /* if we get notification from stack, local shows if we disabled/enabled audio stream */
2258 if (param->notifyinfo.local) switch(param->notifyinfo.notify) {
2259 case INFO_NOTIFY_REMOTE_HOLD:
2260 case INFO_NOTIFY_USER_SUSPENDED:
2261 /* tell call about it */
2262 if (ea_endpoint->ep_join_id) {
2263 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2264 message->param.audiopath = 0;
2265 message_put(message);
2269 case INFO_NOTIFY_REMOTE_RETRIEVAL:
2270 case INFO_NOTIFY_USER_RESUMED:
2271 /* set volume of rx and tx */
2272 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
2273 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
2275 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2276 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2277 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
2278 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
2279 message_put(message);
2281 /* set current tone */
2283 set_tone(portlist, e_tone);
2284 /* tell call about it */
2285 if (ea_endpoint->ep_join_id) {
2286 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2287 message->param.audiopath = 1;
2288 message_put(message);
2293 /* get name of notify */
2294 switch(param->notifyinfo.notify) {
2299 logtext = "USER_SUSPENDED";
2302 logtext = "BEARER_SERVICE_CHANGED";
2305 logtext = "USER_RESUMED";
2308 logtext = "CONFERENCE_ESTABLISHED";
2311 logtext = "CONFERENCE_DISCONNECTED";
2314 logtext = "OTHER_PARTY_ADDED";
2317 logtext = "ISOLATED";
2320 logtext = "REATTACHED";
2323 logtext = "OTHER_PARTY_ISOLATED";
2326 logtext = "OTHER_PARTY_REATTACHED";
2329 logtext = "OTHER_PARTY_SPLIT";
2332 logtext = "OTHER_PARTY_DISCONNECTED";
2335 logtext = "CONFERENCE_FLOATING";
2338 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
2341 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
2344 logtext = "CALL_IS_A_WAITING_CALL";
2347 logtext = "DIVERSION_ACTIVATED";
2350 logtext = "RESERVED_CT_1";
2353 logtext = "RESERVED_CT_2";
2356 logtext = "REVERSE_CHARGING";
2359 logtext = "REMOTE_HOLD";
2362 logtext = "REMOTE_RETRIEVAL";
2365 logtext = "CALL_IS_DIVERTING";
2368 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
2373 /* notify call if available */
2374 if (ea_endpoint->ep_join_id) {
2375 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOTIFY);
2376 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
2377 message_put(message);
2382 /* port MESSAGE_FACILITY */
2383 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
2385 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2387 struct lcr_msg *message;
2389 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_FACILITY);
2390 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2391 message_put(message);
2394 /* port MESSAGE_SUSPEND */
2395 /* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
2396 void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
2398 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2400 /* epoint is now parked */
2401 ea_endpoint->ep_park = 1;
2402 memcpy(ea_endpoint->ep_park_callid, param->parkinfo.callid, sizeof(ea_endpoint->ep_park_callid));
2403 ea_endpoint->ep_park_len = (param->parkinfo.len>8)?8:param->parkinfo.len;
2405 /* remove port relation */
2406 ea_endpoint->free_portlist(portlist);
2409 /* port MESSAGE_RESUME */
2410 /* NOTE: before resume, the active-notification must be done in order to set call mixer */
2411 void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
2413 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2415 /* epoint is now resumed */
2416 ea_endpoint->ep_park = 0;
2421 /* port sends message to the endpoint
2423 void EndpointAppPBX::ea_message_port(unsigned int port_id, int message_type, union parameter *param)
2425 struct port_list *portlist;
2427 portlist = ea_endpoint->ep_portlist;
2429 if (port_id == portlist->port_id)
2431 portlist = portlist->next;
2434 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);
2438 // PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
2439 switch(message_type) {
2440 case MESSAGE_DATA: /* data from port */
2441 /* check if there is a call */
2442 if (!ea_endpoint->ep_join_id)
2444 /* continue if only one portlist */
2445 if (ea_endpoint->ep_portlist->next != NULL)
2447 /* forward message */
2448 message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2451 case MESSAGE_TONE_EOF: /* tone is end of file */
2452 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
2454 if (e_action->index == ACTION_VBOX_PLAY) {
2457 if (e_action->index == ACTION_EFI) {
2463 case MESSAGE_TONE_COUNTER: /* counter info received */
2464 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);
2466 if (e_action->index == ACTION_VBOX_PLAY) {
2467 e_vbox_counter = param->counter.current;
2468 if (param->counter.max >= 0)
2469 e_vbox_counter_max = param->counter.max;
2473 /* PORT sends SETUP message */
2475 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);
2476 if (e_state!=EPOINT_STATE_IDLE) {
2477 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
2480 port_setup(portlist, message_type, param);
2483 /* PORT sends INFORMATION message */
2484 case MESSAGE_INFORMATION: /* additional digits received */
2485 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);
2486 port_information(portlist, message_type, param);
2489 /* PORT sends FACILITY message */
2490 case MESSAGE_FACILITY:
2491 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2492 port_facility(portlist, message_type, param);
2495 /* PORT sends DTMF message */
2496 case MESSAGE_DTMF: /* dtmf digits received */
2497 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);
2498 port_dtmf(portlist, message_type, param);
2501 /* PORT sends CRYPT message */
2502 case MESSAGE_CRYPT: /* crypt response received */
2503 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) crypt response=%d\n", ea_endpoint->ep_serial, param->crypt.type);
2504 port_crypt(portlist, message_type, param);
2507 /* PORT sends MORE message */
2508 case MESSAGE_OVERLAP:
2509 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);
2510 if (e_state != EPOINT_STATE_OUT_SETUP) {
2511 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);
2514 port_overlap(portlist, message_type, param);
2517 /* PORT sends PROCEEDING message */
2518 case MESSAGE_PROCEEDING: /* port is proceeding */
2519 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);
2520 if (e_state!=EPOINT_STATE_OUT_SETUP
2521 && e_state!=EPOINT_STATE_OUT_OVERLAP) {
2522 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);
2525 port_proceeding(portlist, message_type, param);
2528 /* PORT sends ALERTING message */
2529 case MESSAGE_ALERTING:
2530 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);
2531 if (e_state!=EPOINT_STATE_OUT_SETUP
2532 && e_state!=EPOINT_STATE_OUT_OVERLAP
2533 && e_state!=EPOINT_STATE_OUT_PROCEEDING) {
2534 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);
2537 port_alerting(portlist, message_type, param);
2540 /* PORT sends CONNECT message */
2541 case MESSAGE_CONNECT:
2542 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);
2543 if (e_state!=EPOINT_STATE_OUT_SETUP
2544 && e_state!=EPOINT_STATE_OUT_OVERLAP
2545 && e_state!=EPOINT_STATE_OUT_PROCEEDING
2546 && e_state!=EPOINT_STATE_OUT_ALERTING) {
2547 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
2550 port_connect(portlist, message_type, param);
2553 /* PORT sends DISCONNECT message */
2554 case MESSAGE_DISCONNECT: /* port is disconnected */
2555 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);
2556 port_disconnect_release(portlist, message_type, param);
2559 /* PORT sends a RELEASE message */
2560 case MESSAGE_RELEASE: /* port releases */
2561 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);
2562 /* portlist is release at port_disconnect_release, thanx Paul */
2563 port_disconnect_release(portlist, message_type, param);
2566 /* PORT sends a TIMEOUT message */
2567 case MESSAGE_TIMEOUT:
2568 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);
2569 port_timeout(portlist, message_type, param);
2570 break; /* release */
2572 /* PORT sends a NOTIFY message */
2573 case MESSAGE_NOTIFY:
2574 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);
2575 port_notify(portlist, message_type, param);
2578 /* PORT sends a SUSPEND message */
2579 case MESSAGE_SUSPEND:
2580 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);
2581 port_suspend(portlist, message_type, param);
2582 break; /* suspend */
2584 /* PORT sends a RESUME message */
2585 case MESSAGE_RESUME:
2586 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);
2587 port_resume(portlist, message_type, param);
2591 kann nach dem test gelöscht werden, da eine direkte funktion im join und im mISDN zum austausch der message existiert
2592 /* port assigns bchannel */
2593 case MESSAGE_BCHANNEL: /* bchannel assignment messafe */
2594 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);
2595 /* only one port is expected to be connected to bchannel */
2596 message = message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2597 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_IN);
2603 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);
2606 /* Note: this endpoint may be destroyed, so we MUST return */
2610 /* messages from join
2612 /* join MESSAGE_CRYPT */
2613 void EndpointAppPBX::join_crypt(struct port_list *portlist, int message_type, union parameter *param)
2615 switch(param->crypt.type) {
2616 /* message from remote port to "crypt manager" */
2617 case CU_ACTK_REQ: /* activate key-exchange */
2618 case CU_ACTS_REQ: /* activate shared key */
2619 case CU_DACT_REQ: /* deactivate */
2620 case CU_INFO_REQ: /* request last info message */
2621 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2624 /* message from "crypt manager" to user */
2625 case CU_ACTK_CONF: /* key-echange done */
2626 case CU_ACTS_CONF: /* shared key done */
2627 case CU_DACT_CONF: /* deactivated */
2628 case CU_DACT_IND: /* deactivated */
2629 case CU_ERROR_IND: /* receive error message */
2630 case CU_INFO_IND: /* receive info message */
2631 case CU_INFO_CONF: /* receive info message */
2632 encrypt_result(param->crypt.type, (char *)param->crypt.data);
2636 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);
2640 /* join MESSAGE_INFORMATION */
2641 void EndpointAppPBX::join_information(struct port_list *portlist, int message_type, union parameter *param)
2643 struct lcr_msg *message;
2648 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2649 memcpy(&message->param.information, ¶m->information, sizeof(struct dialing_info));
2650 message_put(message);
2651 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2652 portlist = portlist->next;
2656 /* join MESSAGE_FACILITY */
2657 void EndpointAppPBX::join_facility(struct port_list *portlist, int message_type, union parameter *param)
2659 struct lcr_msg *message;
2661 if (!e_ext.facility && e_ext.number[0]) {
2666 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_FACILITY);
2667 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2668 message_put(message);
2669 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2670 portlist = portlist->next;
2674 /* join MESSAGE_MORE */
2675 void EndpointAppPBX::join_overlap(struct port_list *portlist, int message_type, union parameter *param)
2677 struct lcr_msg *message;
2679 new_state(EPOINT_STATE_IN_OVERLAP);
2682 if (e_join_pattern && e_ext.own_setup) {
2683 /* disconnect audio */
2684 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2685 message->param.audiopath = 0;
2686 message_put(message);
2688 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL) {
2689 if (e_dialinginfo.id[0])
2690 set_tone(portlist, "dialing");
2692 set_tone(portlist, "dialtone");
2695 if (e_dialinginfo.id[0]) {
2696 set_tone(portlist, "dialing");
2698 if (e_ext.number[0])
2699 set_tone(portlist, "dialpbx");
2701 set_tone(portlist, "dialtone");
2705 /* join MESSAGE_PROCEEDING */
2706 void EndpointAppPBX::join_proceeding(struct port_list *portlist, int message_type, union parameter *param)
2708 struct lcr_msg *message;
2710 new_state(EPOINT_STATE_IN_PROCEEDING);
2712 /* own proceeding tone */
2713 if (e_join_pattern) {
2714 /* connect / disconnect audio */
2715 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2716 if (e_ext.own_proceeding)
2717 message->param.audiopath = 0;
2719 message->param.audiopath = 1;
2720 message_put(message);
2722 // UCPY(e_join_tone, "proceeding");
2724 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
2725 message_put(message);
2726 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2728 set_tone(portlist, "proceeding");
2731 /* join MESSAGE_ALERTING */
2732 void EndpointAppPBX::join_alerting(struct port_list *portlist, int message_type, union parameter *param)
2734 struct lcr_msg *message;
2736 new_state(EPOINT_STATE_IN_ALERTING);
2738 /* own alerting tone */
2739 if (e_join_pattern) {
2740 /* connect / disconnect audio */
2741 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2742 if (e_ext.own_alerting)
2743 message->param.audiopath = 0;
2745 message->param.audiopath = 1;
2746 message_put(message);
2749 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
2750 message_put(message);
2751 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2753 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL) {
2754 set_tone(portlist, "ringing");
2757 if (e_ext.number[0])
2758 set_tone(portlist, "ringpbx");
2760 set_tone(portlist, "ringing");
2762 if (e_ext.number[0])
2763 e_dtmf = 1; /* allow dtmf */
2766 /* join MESSAGE_CONNECT */
2767 void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type, union parameter *param)
2769 struct lcr_msg *message;
2771 new_state(EPOINT_STATE_CONNECT);
2772 // UCPY(e_join_tone, "");
2774 if (e_ext.number[0])
2775 e_dtmf = 1; /* allow dtmf */
2778 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_callerinfo));
2780 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
2781 memcpy(&message->param, param, sizeof(union parameter));
2783 /* screen clip if prefix is required */
2784 if (e_ext.number[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0]) {
2785 SCPY(message->param.connectinfo.id, e_ext.clip_prefix);
2786 SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype, options.national, options.international));
2787 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2790 /* use internal caller id */
2791 if (e_ext.number[0] && e_connectinfo.extension[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore)) {
2792 SCPY(message->param.connectinfo.id, e_connectinfo.extension);
2793 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2796 /* handle restricted caller ids */
2797 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);
2798 /* display callerid if desired for extension */
2799 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));
2801 /* use conp, if enabld */
2802 // if (!e_ext.centrex)
2803 // message->param.connectinfo.name[0] = '\0';
2806 message_put(message);
2807 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2809 set_tone(portlist, NULL);
2811 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2812 message->param.audiopath = 1;
2813 message_put(message);
2817 /* join MESSAGE_DISCONNECT MESSAGE_RELEASE */
2818 void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *param)
2821 struct lcr_msg *message;
2822 struct port_list *portlist = NULL;
2825 /* be sure that we are active */
2827 e_tx_state = NOTIFY_STATE_ACTIVE;
2829 /* we are powerdialing, if e_powerdialing is set and limit is not exceeded if given */
2830 if (e_powerdialing && ((e_powercount+1)<e_powerlimit || e_powerlimit<1)) {
2831 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
2833 /* set time for power dialing */
2834 e_powerdialing = now_d + e_powerdelay; /* set redial in the future */
2837 /* set redial tone */
2838 if (ea_endpoint->ep_portlist) {
2841 set_tone(ea_endpoint->ep_portlist, "redial");
2842 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);
2843 /* send proceeding when powerdialing and still setup (avoid dialing timeout) */
2844 if (e_state==EPOINT_STATE_IN_OVERLAP) {
2845 new_state(EPOINT_STATE_IN_PROCEEDING);
2846 if (ea_endpoint->ep_portlist) {
2847 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
2848 message_put(message);
2849 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
2851 /* caused the error, that the first knock sound was not there */
2852 /* set_tone(portlist, "proceeding"); */
2854 /* send display of powerdialing */
2855 if (e_ext.display_dialing) {
2856 portlist = ea_endpoint->ep_portlist;
2858 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
2860 SPRINT(message->param.notifyinfo.display, "Retry %d of %d", e_powercount, e_powerlimit);
2862 SPRINT(message->param.notifyinfo.display, "Retry %d", e_powercount);
2863 message_put(message);
2864 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2865 portlist = portlist->next;
2874 if ((e_state!=EPOINT_STATE_CONNECT
2875 && e_state!=EPOINT_STATE_OUT_DISCONNECT
2876 && e_state!=EPOINT_STATE_IN_OVERLAP
2877 && e_state!=EPOINT_STATE_IN_PROCEEDING
2878 && e_state!=EPOINT_STATE_IN_ALERTING)
2879 || !ea_endpoint->ep_portlist) { /* or no port */
2880 process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
2881 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause); /* RELEASE_TYPE, join, port */
2882 return; /* must exit here */
2885 if (!e_join_cause) {
2886 e_join_cause = param->disconnectinfo.cause;
2887 e_join_location = param->disconnectinfo.location;
2890 /* on release we need the audio again! */
2891 if (message_type == MESSAGE_RELEASE) {
2893 ea_endpoint->ep_join_id = 0;
2895 /* disconnect and select tone */
2896 new_state(EPOINT_STATE_OUT_DISCONNECT);
2897 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2898 /* if own_cause, we must release the join */
2899 if (e_ext.own_cause /* own cause */
2900 || !e_join_pattern) { /* no patterns */
2901 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);
2902 if (message_type != MESSAGE_RELEASE)
2903 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
2905 } else { /* else we enable audio */
2906 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2907 message->param.audiopath = 1;
2908 message_put(message);
2910 /* send disconnect message */
2911 SCPY(e_tone, cause);
2912 portlist = ea_endpoint->ep_portlist;
2914 set_tone(portlist, cause);
2915 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2916 portlist = portlist->next;
2920 /* join MESSAGE_SETUP */
2921 void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, union parameter *param)
2923 struct lcr_msg *message;
2924 // struct interface *interface;
2926 /* if we already in setup state, we just update the dialing with new digits */
2927 if (e_state == EPOINT_STATE_OUT_SETUP
2928 || e_state == EPOINT_STATE_OUT_OVERLAP) {
2929 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we are in setup state, so we do overlap dialing.\n", ea_endpoint->ep_serial);
2930 /* if digits changed, what we have already dialed */
2931 if (!!strncmp(e_dialinginfo.id,param->setup.dialinginfo.id,strlen(e_dialinginfo.id))) {
2932 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);
2933 /* release all ports */
2934 while((portlist = ea_endpoint->ep_portlist)) {
2935 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2936 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2937 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2938 message_put(message);
2939 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2940 ea_endpoint->free_portlist(portlist);
2943 /* disconnect audio */
2944 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2945 message->param.audiopath = 0;
2946 message_put(message);
2948 /* get dialing info */
2949 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
2950 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
2951 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
2952 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
2953 new_state(EPOINT_STATE_OUT_OVERLAP);
2956 e_redial = now_d + 1; /* set redial one second in the future */
2959 /* if we have a pending redial, so we just adjust the dialing number */
2961 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);
2962 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
2965 if (!ea_endpoint->ep_portlist) {
2966 PERROR("ERROR: overlap dialing to a NULL port relation\n");
2968 if (ea_endpoint->ep_portlist->next) {
2969 PERROR("ERROR: overlap dialing to a port_list port relation\n");
2971 if (e_state == EPOINT_STATE_OUT_SETUP) {
2973 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);
2974 SCAT(e_dialing_queue, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
2977 /* get what we have not dialed yet */
2978 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));
2979 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2980 SCPY(message->param.information.id, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
2981 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
2982 message_put(message);
2983 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
2985 /* always store what we have dialed or queued */
2986 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
2990 if (e_state != EPOINT_STATE_IDLE) {
2991 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
2994 /* if an internal extension is dialed, copy that number */
2995 if (param->setup.dialinginfo.itype==INFO_ITYPE_ISDN_EXTENSION || param->setup.dialinginfo.itype==INFO_ITYPE_VBOX)
2996 SCPY(e_ext.number, param->setup.dialinginfo.id);
2997 /* if an internal extension is dialed, get extension's info about caller */
2998 if (e_ext.number[0]) {
2999 if (!read_extension(&e_ext, e_ext.number)) {
3000 e_ext.number[0] = '\0';
3001 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the called terminal='%s' is not found in directory tree!\n", ea_endpoint->ep_serial, e_ext.number);
3005 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3006 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3007 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3008 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3010 /* process (voice over) data calls */
3011 if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO) {
3012 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) handling data call as audio call: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
3013 memset(&e_capainfo, 0, sizeof(e_capainfo));
3014 e_capainfo.bearer_capa = INFO_BC_AUDIO;
3015 e_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
3016 e_capainfo.bearer_info1 = (options.law=='u')?INFO_INFO1_ULAW:INFO_INFO1_ALAW;
3019 new_state(EPOINT_STATE_OUT_SETUP);
3020 /* call special setup routine */
3024 /* join MESSAGE_mISDNSIGNAL */
3025 void EndpointAppPBX::join_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param)
3027 struct lcr_msg *message;
3030 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
3031 memcpy(&message->param, param, sizeof(union parameter));
3032 message_put(message);
3033 portlist = portlist->next;
3037 /* join MESSAGE_NOTIFY */
3038 void EndpointAppPBX::join_notify(struct port_list *portlist, int message_type, union parameter *param)
3040 struct lcr_msg *message;
3043 if (param->notifyinfo.notify) {
3044 new_state = track_notify(e_tx_state, param->notifyinfo.notify);
3045 // /* if notification was generated locally, we turn hold music on/off */
3046 // if (param->notifyinfo.local)
3047 // 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)
3051 if (new_state!=NOTIFY_STATE_HOLD && new_state!=NOTIFY_STATE_SUSPEND) {
3052 if (!strcmp(e_tone, "hold")) { // don't interrupt other tones
3054 set_tone(portlist, "");
3055 portlist = portlist->next;
3058 portlist = ea_endpoint->ep_portlist;
3063 if (new_state==NOTIFY_STATE_HOLD || new_state==NOTIFY_STATE_SUSPEND) {
3065 set_tone(portlist, "hold");
3066 portlist = portlist->next;
3068 portlist = ea_endpoint->ep_portlist;
3073 /* save new state */
3074 e_tx_state = new_state;
3077 /* notify port(s) about it */
3079 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3080 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
3081 /* handle restricted caller ids */
3082 apply_callerid_restriction(&e_ext, message->param.notifyinfo.id, &message->param.notifyinfo.ntype, &message->param.notifyinfo.present, 0, message->param.notifyinfo.extension, NULL);
3083 /* display callerid if desired for extension */
3084 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));
3085 message_put(message);
3086 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3087 portlist = portlist->next;
3091 /* JOIN sends messages to the endpoint
3093 void EndpointAppPBX::ea_message_join(unsigned int join_id, int message_type, union parameter *param)
3095 struct port_list *portlist;
3096 struct lcr_msg *message;
3099 PERROR("EPOINT(%d) error: JOIN == NULL.\n", ea_endpoint->ep_serial);
3103 portlist = ea_endpoint->ep_portlist;
3105 /* send MESSAGE_DATA to port */
3106 if (message_type == MESSAGE_DATA) {
3107 if (join_id == ea_endpoint->ep_join_id) { // still linked with JOIN
3108 /* skip if no port relation */
3111 /* skip if more than one port relation */
3114 /* forward audio data to port */
3115 message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3120 // 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);
3121 switch(message_type) {
3122 /* JOIN SENDS TONE message */
3124 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);
3125 set_tone(portlist, param->tone.name);
3128 /* JOIN SENDS CRYPT message */
3130 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);
3131 join_crypt(portlist, message_type, param);
3134 /* JOIN sends INFORMATION message */
3135 case MESSAGE_INFORMATION:
3136 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);
3137 join_information(portlist, message_type, param);
3140 /* JOIN sends FACILITY message */
3141 case MESSAGE_FACILITY:
3142 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);
3143 join_facility(portlist, message_type, param);
3146 /* JOIN sends OVERLAP message */
3147 case MESSAGE_OVERLAP:
3148 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);
3149 if (e_state!=EPOINT_STATE_IN_SETUP
3150 && e_state!=EPOINT_STATE_IN_OVERLAP) {
3151 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3154 join_overlap(portlist, message_type, param);
3157 /* JOIN sends PROCEEDING message */
3158 case MESSAGE_PROCEEDING:
3159 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);
3160 if(e_state!=EPOINT_STATE_IN_OVERLAP) {
3161 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3164 join_proceeding(portlist, message_type, param);
3167 /* JOIN sends ALERTING message */
3168 case MESSAGE_ALERTING:
3169 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);
3170 if (e_state!=EPOINT_STATE_IN_OVERLAP
3171 && e_state!=EPOINT_STATE_IN_PROCEEDING) {
3172 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state.\n", ea_endpoint->ep_serial);
3175 join_alerting(portlist, message_type, param);
3178 /* JOIN sends CONNECT message */
3179 case MESSAGE_CONNECT:
3180 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);
3181 if (e_state!=EPOINT_STATE_IN_OVERLAP
3182 && e_state!=EPOINT_STATE_IN_PROCEEDING
3183 && e_state!=EPOINT_STATE_IN_ALERTING) {
3184 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
3187 join_connect(portlist, message_type, param);
3190 /* JOIN sends DISCONNECT/RELEASE message */
3191 case MESSAGE_DISCONNECT: /* JOIN disconnect */
3192 case MESSAGE_RELEASE: /* JOIN releases */
3193 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);
3194 join_disconnect_release(message_type, param);
3197 /* JOIN sends SETUP message */
3199 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);
3200 join_setup(portlist, message_type, param);
3203 /* JOIN sends special mISDNSIGNAL message */
3204 case MESSAGE_mISDNSIGNAL: /* isdn message to port */
3205 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);
3206 join_mISDNsignal(portlist, message_type, param);
3210 kann nach dem test gelöscht werden, da eine direkte funktion im join und im mISDN zum austausch der message existiert
3211 /* JOIN requests bchannel */
3212 case MESSAGE_BCHANNEL: /* indicates the need of own bchannel access */
3213 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);
3214 /* only one port is expected to be connected to bchannel */
3221 set_tone(portlist, NULL);
3222 message = message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3223 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3227 /* JOIN has pattern available */
3228 case MESSAGE_PATTERN: /* indicating pattern available */
3229 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);
3230 if (!e_join_pattern) {
3231 PDEBUG(DEBUG_EPOINT, "-> pattern becomes available\n");
3235 set_tone(portlist, NULL);
3236 portlist = portlist->next;
3238 /* connect our audio tx and rx (blueboxing should be possibe before connect :)*/
3239 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3240 message->param.audiopath = 1;
3241 message_put(message);
3245 /* JOIN has no pattern available */
3246 case MESSAGE_NOPATTERN: /* indicating no pattern available */
3247 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);
3248 if (e_join_pattern) {
3249 PDEBUG(DEBUG_EPOINT, "-> pattern becomes unavailable\n");
3251 /* disconnect our audio tx and rx */
3252 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3253 message->param.audiopath = 0;
3254 message_put(message);
3259 /* JOIN (dunno at the moment) */
3260 case MESSAGE_REMOTE_AUDIO:
3261 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);
3262 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3263 message->param.audiopath = param->channel;
3264 message_put(message);
3268 /* JOIN sends a notify message */
3269 case MESSAGE_NOTIFY:
3270 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);
3271 join_notify(portlist, message_type, param);
3274 /* JOIN wants keypad / dtmf */
3275 case MESSAGE_ENABLEKEYPAD:
3276 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);
3279 trace_header("ENABLE KEYPAD", DIRECTION_NONE);
3284 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);
3289 /* pick_join will connect the first incoming call found. the endpoint
3290 * will receivce a MESSAGE_CONNECT.
3292 int match_list(char *list, char *item)
3294 char *end, *next = NULL;
3296 /* no list make matching */
3301 /* eliminate white spaces */
3302 while (*list <= ' ')
3308 /* if end of list is reached, we return */
3309 if (list[0] == '\0')
3311 /* if we have more than one entry (left) */
3312 if ((end = strchr(list, ',')))
3315 next = end = strchr(list, '\0');
3316 while (*(end-1) <= ' ')
3318 /* if string part matches item */
3319 if (!strncmp(list, item, end-list))
3325 void EndpointAppPBX::pick_join(char *extensions)
3327 struct lcr_msg *message;
3328 struct port_list *portlist;
3330 class EndpointAppPBX *eapp, *found;
3332 class JoinPBX *joinpbx;
3333 struct join_relation *relation;
3336 /* find an endpoint that is ringing internally or vbox with higher priority */
3339 eapp = apppbx_first;
3341 if (eapp!=this && ea_endpoint->ep_portlist) {
3342 portlist = eapp->ea_endpoint->ep_portlist;
3344 if ((port = find_port_id(portlist->port_id))) {
3345 if (port->p_type == PORT_TYPE_VBOX_OUT) {
3346 if (match_list(extensions, eapp->e_ext.number)) {
3352 if ((port->p_type==PORT_TYPE_DSS1_NT_OUT || port->p_type==PORT_TYPE_DSS1_TE_OUT || port->p_type==PORT_TYPE_GSM_OUT)
3353 && port->p_state==PORT_STATE_OUT_ALERTING)
3354 if (match_list(extensions, eapp->e_ext.number)) {
3358 portlist = portlist->next;
3366 /* if no endpoint found */
3368 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);
3370 set_tone(ea_endpoint->ep_portlist, "cause_10");
3371 message_disconnect_port(ea_endpoint->ep_portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
3372 new_state(EPOINT_STATE_OUT_DISCONNECT);
3377 if (ea_endpoint->ep_join_id) {
3378 PERROR("EPOINT(%d) we already have a join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3381 if (!eapp->ea_endpoint->ep_join_id) {
3382 PERROR("EPOINT(%d) ringing endpoint has no join.\n", ea_endpoint->ep_serial);
3385 join = find_join_id(eapp->ea_endpoint->ep_join_id);
3387 PERROR("EPOINT(%d) ringing endpoint's join not found.\n", ea_endpoint->ep_serial);
3390 if (join->j_type != JOIN_TYPE_PBX) {
3391 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ringing endpoint's join is not a PBX join, so we must reject.\n", ea_endpoint->ep_serial);
3394 joinpbx = (class JoinPBX *)join;
3395 relation = joinpbx->j_relation;
3397 PERROR("EPOINT(%d) ringing endpoint's join has no relation. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3400 while (relation->epoint_id != eapp->ea_endpoint->ep_serial) {
3401 relation = relation->next;
3403 PERROR("EPOINT(%d) ringing endpoint's join has no relation to that join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3408 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found ringing endpoint: %d.\n", ea_endpoint->ep_serial, eapp->ea_endpoint->ep_serial);
3410 if (options.deb & DEBUG_EPOINT) {
3411 class Join *debug_c = join_first;
3412 class Endpoint *debug_e = epoint_first;
3413 class Port *debug_p = port_first;
3415 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(before)");
3417 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3419 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3420 debug_c = debug_c->next;
3422 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3424 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3425 debug_e = debug_e->next;
3427 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3429 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld (active)\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3430 debug_p = debug_p->next;
3435 ea_endpoint->ep_join_id = eapp->ea_endpoint->ep_join_id; /* we get the join */
3436 relation->epoint_id = ea_endpoint->ep_serial; /* the join gets us */
3437 eapp->ea_endpoint->ep_join_id = 0; /* the ringing endpoint will get disconnected */
3439 /* connnecting our endpoint */
3440 new_state(EPOINT_STATE_CONNECT);
3441 if (e_ext.number[0])
3443 set_tone(ea_endpoint->ep_portlist, NULL);
3445 /* now we send a release to the ringing endpoint */
3446 message = message_create(ea_endpoint->ep_join_id, eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3447 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
3448 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3449 message_put(message);
3451 /* we send a connect to the join with our caller id */
3452 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CONNECT);
3453 SCPY(message->param.connectinfo.id, e_callerinfo.id);
3454 message->param.connectinfo.present = e_callerinfo.present;
3455 message->param.connectinfo.screen = e_callerinfo.screen;
3456 message->param.connectinfo.itype = e_callerinfo.itype;
3457 message->param.connectinfo.ntype = e_callerinfo.ntype;
3458 message_put(message);
3460 /* we send a connect to our port with the remote callerid */
3461 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3462 SCPY(message->param.connectinfo.id, eapp->e_callerinfo.id);
3463 message->param.connectinfo.present = eapp->e_callerinfo.present;
3464 message->param.connectinfo.screen = eapp->e_callerinfo.screen;
3465 message->param.connectinfo.itype = eapp->e_callerinfo.itype;
3466 message->param.connectinfo.ntype = eapp->e_callerinfo.ntype;
3467 /* handle restricted caller ids */
3468 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);
3469 /* display callerid if desired for extension */
3470 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));
3471 message_put(message);
3473 /* we send a connect to the audio path (not for vbox) */
3474 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3475 message->param.audiopath = 1;
3476 message_put(message);
3478 /* beeing paranoid, we make call update */
3479 joinpbx->j_updatebridge = 1;
3481 if (options.deb & DEBUG_EPOINT) {
3482 class Join *debug_c = join_first;
3483 class Endpoint *debug_e = epoint_first;
3484 class Port *debug_p = port_first;
3486 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(after)");
3488 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3490 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3491 debug_c = debug_c->next;
3493 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3495 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3496 debug_e = debug_e->next;
3498 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3500 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3501 debug_p = debug_p->next;
3507 /* join calls (look for a join that is on hold (same isdn interface/terminal))
3509 void EndpointAppPBX::join_join(void)
3511 struct lcr_msg *message;
3512 struct join_relation *our_relation, *other_relation;
3513 struct join_relation **our_relation_pointer, **other_relation_pointer;
3514 class Join *our_join, *other_join;
3515 class JoinPBX *our_joinpbx, *other_joinpbx;
3516 class EndpointAppPBX *other_eapp; class Endpoint *temp_epoint;
3517 class Port *our_port, *other_port;
3518 class Pdss1 *our_pdss1, *other_pdss1;
3520 /* are we a candidate to join a join? */
3521 our_join = find_join_id(ea_endpoint->ep_join_id);
3523 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3526 if (our_join->j_type != JOIN_TYPE_PBX) {
3527 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: join is not a pbx join.\n", ea_endpoint->ep_serial);
3530 our_joinpbx = (class JoinPBX *)our_join;
3531 if (!ea_endpoint->ep_portlist) {
3532 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
3535 if (!e_ext.number[0]) {
3536 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
3539 our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
3541 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
3544 if ((our_port->p_type&PORT_CLASS_mISDN_MASK) != PORT_CLASS_mISDN_DSS1) {
3545 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not isdn.\n", ea_endpoint->ep_serial);
3548 our_pdss1 = (class Pdss1 *)our_port;
3550 /* find an endpoint that is on hold and has the same mISDNport that we are on */
3551 other_eapp = apppbx_first;
3553 if (other_eapp == this) {
3554 other_eapp = other_eapp->next;
3557 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);
3558 if (other_eapp->e_ext.number[0] /* has terminal */
3559 && other_eapp->ea_endpoint->ep_portlist /* has port */
3560 && other_eapp->ea_endpoint->ep_join_id) { /* has join */
3561 other_port = find_port_id(other_eapp->ea_endpoint->ep_portlist->port_id);
3562 if (other_port) { /* port still exists */
3563 if (other_port->p_type==PORT_TYPE_DSS1_NT_OUT
3564 || other_port->p_type==PORT_TYPE_DSS1_NT_IN) { /* port is isdn nt-mode */
3565 other_pdss1 = (class Pdss1 *)other_port;
3566 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);
3567 if (other_pdss1->p_m_hold /* port is on hold */
3568 && other_pdss1->p_m_mISDNport == our_pdss1->p_m_mISDNport /* same isdn interface */
3569 && other_pdss1->p_m_d_ces == our_pdss1->p_m_d_ces) /* same tei+sapi */
3572 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of other type!\n", ea_endpoint->ep_serial);
3575 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port doesn't exist enymore.\n", ea_endpoint->ep_serial);
3578 other_eapp = other_eapp->next;
3581 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn terminal.\n", ea_endpoint->ep_serial);
3584 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port with same terminal found.\n", ea_endpoint->ep_serial);
3586 /* if we have the same join */
3587 if (other_eapp->ea_endpoint->ep_join_id == ea_endpoint->ep_join_id) {
3588 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we and the other have the same join.\n", ea_endpoint->ep_serial);
3591 other_join = find_join_id(other_eapp->ea_endpoint->ep_join_id);
3593 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3596 if (other_join->j_type != JOIN_TYPE_PBX) {
3597 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join is not a pbx join.\n", ea_endpoint->ep_serial);
3600 other_joinpbx = (class JoinPBX *)other_join;
3601 if (our_joinpbx->j_partyline && other_joinpbx->j_partyline) {
3602 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both joins are partylines.\n", ea_endpoint->ep_serial);
3606 /* remove relation to endpoint for join on hold */
3607 other_relation = other_joinpbx->j_relation;
3608 other_relation_pointer = &other_joinpbx->j_relation;
3609 while(other_relation) {
3610 if (other_relation->epoint_id == other_eapp->ea_endpoint->ep_serial) {
3611 /* detach other endpoint on hold */
3612 *other_relation_pointer = other_relation->next;
3613 FREE(other_relation, sizeof(struct join_relation));
3615 other_relation = *other_relation_pointer;
3616 other_eapp->ea_endpoint->ep_join_id = 0;
3620 /* change join/hold pointer of endpoint to the new join */
3621 temp_epoint = find_epoint_id(other_relation->epoint_id);
3623 if (temp_epoint->ep_join_id == other_join->j_serial)
3624 temp_epoint->ep_join_id = our_join->j_serial;
3627 other_relation_pointer = &other_relation->next;
3628 other_relation = other_relation->next;
3630 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint on hold removed, other enpoints on join relinked (to our join).\n", ea_endpoint->ep_serial);
3632 /* join call relations */
3633 our_relation = our_joinpbx->j_relation;
3634 our_relation_pointer = &our_joinpbx->j_relation;
3635 while(our_relation) {
3636 our_relation_pointer = &our_relation->next;
3637 our_relation = our_relation->next;
3639 *our_relation_pointer = other_joinpbx->j_relation;
3640 other_joinpbx->j_relation = NULL;
3641 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) relations joined.\n", ea_endpoint->ep_serial);
3643 /* release endpoint on hold */
3644 message = message_create(other_joinpbx->j_serial, other_eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3645 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */
3646 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3647 message_put(message);
3649 /* if we are not a partyline, we get partyline state from other join */
3650 our_joinpbx->j_partyline += other_joinpbx->j_partyline;
3652 /* remove empty join */
3654 PDEBUG(DEBUG_EPOINT, "EPOINT(%d)d-join completely removed!\n");
3656 /* mixer must update */
3657 our_joinpbx->j_updatebridge = 1; /* update mixer flag */
3659 /* we send a retrieve to that endpoint */
3660 // mixer will update the hold-state of the join and send it to the endpoints is changes
3664 /* check if we have an external call
3665 * this is used to check for encryption ability
3667 int EndpointAppPBX::check_external(const char **errstr, class Port **port)
3669 struct join_relation *relation;
3671 class JoinPBX *joinpbx;
3672 class Endpoint *epoint;
3674 /* some paranoia check */
3675 if (!ea_endpoint->ep_portlist) {
3676 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we have no port.\n", ea_endpoint->ep_serial);
3677 *errstr = "No Call";
3680 if (!e_ext.number[0]) {
3681 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we are not internal extension.\n", ea_endpoint->ep_serial);
3682 *errstr = "No Call";
3686 /* check if we have a join with 2 parties */
3687 join = find_join_id(ea_endpoint->ep_join_id);
3689 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have currently no join.\n", ea_endpoint->ep_serial);
3690 *errstr = "No Call";
3693 if (join->j_type != JOIN_TYPE_PBX) {
3694 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join is not a pbx join.\n", ea_endpoint->ep_serial);
3695 *errstr = "No PBX Call";
3698 joinpbx = (class JoinPBX *)join;
3699 relation = joinpbx->j_relation;
3701 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no relation.\n", ea_endpoint->ep_serial);
3702 *errstr = "No Call";
3705 if (!relation->next) {
3706 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd relation.\n", ea_endpoint->ep_serial);
3707 *errstr = "No Call";
3710 if (relation->next->next) {
3711 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has more than two relations.\n", ea_endpoint->ep_serial);
3712 *errstr = "Err: Conference";
3715 if (relation->epoint_id == ea_endpoint->ep_serial) {
3716 relation = relation->next;
3717 if (relation->epoint_id == ea_endpoint->ep_serial) {
3718 PERROR("EPOINT(%d) SOFTWARE ERROR: both join relations are related to our endpoint.\n", ea_endpoint->ep_serial);
3719 *errstr = "Software Error";
3724 /* check remote port for external call */
3725 epoint = find_epoint_id(relation->epoint_id);
3727 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd endpoint.\n", ea_endpoint->ep_serial);
3728 *errstr = "No Call";
3731 if (!epoint->ep_portlist) {
3732 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not port.\n", ea_endpoint->ep_serial);
3733 *errstr = "No Call";
3736 *port = find_port_id(epoint->ep_portlist->port_id);
3738 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has an none existing port.\n", ea_endpoint->ep_serial);
3739 *errstr = "No Call";
3742 if (((*port)->p_type&PORT_CLASS_mISDN_MASK)!=PORT_CLASS_mISDN_DSS1) { /* port is not external isdn */
3743 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not an external port.\n", ea_endpoint->ep_serial);
3744 *errstr = "No Ext Call";
3747 if ((*port)->p_state != PORT_STATE_CONNECT) {
3748 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint's port is not in connected state.\n", ea_endpoint->ep_serial);
3749 *errstr = "No Ext Connect";
3755 void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsigned int port_id, int dir)
3757 const char *logtext = "unknown";
3760 switch(message_type) {
3762 trace_header("SETUP", dir);
3763 if (dir == DIRECTION_OUT)
3764 add_trace("to", NULL, "CH(%lu)", port_id);
3765 if (dir == DIRECTION_IN)
3766 add_trace("from", NULL, "CH(%lu)", port_id);
3767 if (param->setup.callerinfo.extension[0])
3768 add_trace("extension", NULL, "%s", param->setup.callerinfo.extension);
3769 add_trace("caller id", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype, options.national, options.international));
3770 switch(param->setup.callerinfo.present) {
3771 case INFO_PRESENT_RESTRICTED:
3772 add_trace("caller id", "present", "restricted");
3774 case INFO_PRESENT_ALLOWED:
3775 add_trace("caller id", "present", "allowed");
3778 add_trace("caller id", "present", "not available");
3780 if (param->setup.callerinfo.ntype2) {
3781 add_trace("caller id2", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id2, param->setup.callerinfo.ntype2, options.national, options.international));
3782 switch(param->setup.callerinfo.present) {
3783 case INFO_PRESENT_RESTRICTED:
3784 add_trace("caller id2", "present", "restricted");
3786 case INFO_PRESENT_ALLOWED:
3787 add_trace("caller id2", "present", "allowed");
3790 add_trace("caller id2", "present", "not available");
3793 if (param->setup.redirinfo.id[0]) {
3794 add_trace("redir'ing", "number", "%s", numberrize_callerinfo(param->setup.redirinfo.id, param->setup.redirinfo.ntype, options.national, options.international));
3795 switch(param->setup.redirinfo.present) {
3796 case INFO_PRESENT_RESTRICTED:
3797 add_trace("redir'ing", "present", "restricted");
3799 case INFO_PRESENT_ALLOWED:
3800 add_trace("redir'ing", "present", "allowed");
3803 add_trace("redir'ing", "present", "not available");
3806 if (param->setup.dialinginfo.id[0])
3807 add_trace("dialing", NULL, "%s", param->setup.dialinginfo.id);
3808 if (param->setup.dialinginfo.display[0])
3809 add_trace("display", NULL, "%s", param->setup.dialinginfo.display);
3810 if (param->setup.dialinginfo.sending_complete)
3811 add_trace("complete", NULL, "true", param->setup.dialinginfo.sending_complete);
3815 case MESSAGE_OVERLAP:
3816 trace_header("SETUP ACKNOWLEDGE", dir);
3817 if (dir == DIRECTION_OUT)
3818 add_trace("to", NULL, "CH(%lu)", port_id);
3819 if (dir == DIRECTION_IN)
3820 add_trace("from", NULL, "CH(%lu)", port_id);
3824 case MESSAGE_PROCEEDING:
3825 trace_header("PROCEEDING", dir);
3826 if (dir == DIRECTION_OUT)
3827 add_trace("to", NULL, "CH(%lu)", port_id);
3828 if (dir == DIRECTION_IN)
3829 add_trace("from", NULL, "CH(%lu)", port_id);
3833 case MESSAGE_ALERTING:
3834 trace_header("ALERTING", dir);
3835 if (dir == DIRECTION_OUT)
3836 add_trace("to", NULL, "CH(%lu)", port_id);
3837 if (dir == DIRECTION_IN)
3838 add_trace("from", NULL, "CH(%lu)", port_id);
3842 case MESSAGE_CONNECT:
3843 trace_header("CONNECT", dir);
3844 if (dir == DIRECTION_OUT)
3845 add_trace("to", NULL, "CH(%lu)", port_id);
3846 if (dir == DIRECTION_IN)
3847 add_trace("from", NULL, "CH(%lu)", port_id);
3848 if (param->connectinfo.extension[0])
3849 add_trace("extension", NULL, "%s", param->connectinfo.extension);
3850 add_trace("connect id", "number", "%s", numberrize_callerinfo(param->connectinfo.id, param->connectinfo.ntype, options.national, options.international));
3851 switch(param->connectinfo.present) {
3852 case INFO_PRESENT_RESTRICTED:
3853 add_trace("connect id", "present", "restricted");
3855 case INFO_PRESENT_ALLOWED:
3856 add_trace("connect id", "present", "allowed");
3859 add_trace("connect id", "present", "not available");
3861 if (param->connectinfo.display[0])
3862 add_trace("display", NULL, "%s", param->connectinfo.display);
3866 case MESSAGE_DISCONNECT:
3867 case MESSAGE_RELEASE:
3868 if (message_type == MESSAGE_DISCONNECT)
3869 trace_header("DISCONNECT", dir);
3871 trace_header("RELEASE", dir);
3872 if (dir == DIRECTION_OUT)
3873 add_trace("to", NULL, "CH(%lu)", port_id);
3874 if (dir == DIRECTION_IN)
3875 add_trace("from", NULL, "CH(%lu)", port_id);
3876 add_trace("cause", "value", "%d", param->disconnectinfo.cause);
3877 switch(param->disconnectinfo.location) {
3879 add_trace("cause", "location", "0-User");
3881 case LOCATION_PRIVATE_LOCAL:
3882 add_trace("cause", "location", "1-Local-PBX");
3884 case LOCATION_PUBLIC_LOCAL:
3885 add_trace("cause", "location", "2-Local-Exchange");
3887 case LOCATION_TRANSIT:
3888 add_trace("cause", "location", "3-Transit");
3890 case LOCATION_PUBLIC_REMOTE:
3891 add_trace("cause", "location", "4-Remote-Exchange");
3893 case LOCATION_PRIVATE_REMOTE:
3894 add_trace("cause", "location", "5-Remote-PBX");
3896 case LOCATION_INTERNATIONAL:
3897 add_trace("cause", "location", "7-International-Exchange");
3899 case LOCATION_BEYOND:
3900 add_trace("cause", "location", "10-Beyond-Interworking");
3903 add_trace("cause", "location", "%d", param->disconnectinfo.location);
3905 if (param->disconnectinfo.display[0])
3906 add_trace("display", NULL, "%s", param->disconnectinfo.display);
3910 case MESSAGE_NOTIFY:
3911 switch(param->notifyinfo.notify) {
3916 logtext = "USER_SUSPENDED";
3919 logtext = "BEARER_SERVICE_CHANGED";
3922 logtext = "USER_RESUMED";
3925 logtext = "CONFERENCE_ESTABLISHED";
3928 logtext = "CONFERENCE_DISCONNECTED";
3931 logtext = "OTHER_PARTY_ADDED";
3934 logtext = "ISOLATED";
3937 logtext = "REATTACHED";
3940 logtext = "OTHER_PARTY_ISOLATED";
3943 logtext = "OTHER_PARTY_REATTACHED";
3946 logtext = "OTHER_PARTY_SPLIT";
3949 logtext = "OTHER_PARTY_DISCONNECTED";
3952 logtext = "CONFERENCE_FLOATING";
3955 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
3958 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
3961 logtext = "CALL_IS_A_WAITING_CALL";
3964 logtext = "DIVERSION_ACTIVATED";
3967 logtext = "RESERVED_CT_1";
3970 logtext = "RESERVED_CT_2";
3973 logtext = "REVERSE_CHARGING";
3976 logtext = "REMOTE_HOLD";
3979 logtext = "REMOTE_RETRIEVAL";
3982 logtext = "CALL_IS_DIVERTING";
3985 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
3989 trace_header("NOTIFY", dir);
3990 if (dir == DIRECTION_OUT)
3991 add_trace("to", NULL, "CH(%lu)", port_id);
3992 if (dir == DIRECTION_IN)
3993 add_trace("from", NULL, "CH(%lu)", port_id);
3994 if (param->notifyinfo.notify)
3995 add_trace("indicator", NULL, "%s", logtext);
3996 if (param->notifyinfo.id[0]) {
3997 add_trace("redir'on", "number", "%s", numberrize_callerinfo(param->notifyinfo.id, param->notifyinfo.ntype, options.national, options.international));
3998 switch(param->notifyinfo.present) {
3999 case INFO_PRESENT_RESTRICTED:
4000 add_trace("redir'on", "present", "restricted");
4002 case INFO_PRESENT_ALLOWED:
4003 add_trace("redir'on", "present", "allowed");
4006 add_trace("redir'on", "present", "not available");
4009 if (param->notifyinfo.display[0])
4010 add_trace("display", NULL, "%s", param->notifyinfo.display);
4014 case MESSAGE_INFORMATION:
4015 trace_header("INFORMATION", dir);
4016 if (dir == DIRECTION_OUT)
4017 add_trace("to", NULL, "CH(%lu)", port_id);
4018 if (dir == DIRECTION_IN)
4019 add_trace("from", NULL, "CH(%lu)", port_id);
4020 if (param->information.id[0])
4021 add_trace("dialing", NULL, "%s", param->information.id);
4022 if (param->information.display[0])
4023 add_trace("display", NULL, "%s", param->information.display);
4024 if (param->information.sending_complete)
4025 add_trace("complete", NULL, "true", param->information.sending_complete);
4029 case MESSAGE_FACILITY:
4030 trace_header("FACILITY", dir);
4031 if (dir == DIRECTION_OUT)
4032 add_trace("to", NULL, "CH(%lu)", port_id);
4033 if (dir == DIRECTION_IN)
4034 add_trace("from", NULL, "CH(%lu)", port_id);
4039 trace_header("TONE", dir);
4040 if (dir == DIRECTION_OUT)
4041 add_trace("to", NULL, "CH(%lu)", port_id);
4042 if (dir == DIRECTION_IN)
4043 add_trace("from", NULL, "CH(%lu)", port_id);
4044 if (param->tone.name[0]) {
4045 add_trace("directory", NULL, "%s", param->tone.dir[0]?param->tone.dir:"default");
4046 add_trace("name", NULL, "%s", param->tone.name);
4048 add_trace("off", NULL, NULL);
4052 case MESSAGE_SUSPEND:
4053 case MESSAGE_RESUME:
4054 if (message_type == MESSAGE_SUSPEND)
4055 trace_header("SUSPEND", dir);
4057 trace_header("RESUME", dir);
4058 if (dir == DIRECTION_OUT)
4059 add_trace("to", NULL, "CH(%lu)", port_id);
4060 if (dir == DIRECTION_IN)
4061 add_trace("from", NULL, "CH(%lu)", port_id);
4062 if (param->parkinfo.len)
4063 add_trace("length", NULL, "%d", param->parkinfo.len);
4068 case MESSAGE_BCHANNEL:
4069 trace_header("BCHANNEL", dir);
4070 switch(param->bchannel.type) {
4071 case BCHANNEL_REQUEST:
4072 add_trace("type", NULL, "request");
4074 case BCHANNEL_ASSIGN:
4075 add_trace("type", NULL, "assign");
4077 case BCHANNEL_ASSIGN_ACK:
4078 add_trace("type", NULL, "assign_ack");
4080 case BCHANNEL_REMOVE:
4081 add_trace("type", NULL, "remove");
4083 case BCHANNEL_REMOVE_ACK:
4084 add_trace("type", NULL, "remove_ack");
4087 if (param->bchannel.addr)
4088 add_trace("address", NULL, "%x", param->bchannel.addr);
4094 PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message_type);
4098 void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cause, int location, const char *display)
4100 struct lcr_msg *message;
4104 if (!portlist->port_id)
4107 if (!e_connectedmode) {
4108 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT);
4109 message->param.disconnectinfo.cause = cause;
4110 message->param.disconnectinfo.location = location;
4112 SCPY(message->param.disconnectinfo.display, display);
4114 SCPY(message->param.disconnectinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4116 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
4118 SCPY(message->param.notifyinfo.display, display);
4120 SCPY(message->param.notifyinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4122 message_put(message);
4123 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);