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;
122 FATAL("Endpoint not in endpoint's list.\n");
129 * trace header for application
131 void EndpointAppPBX::trace_header(const char *name, int direction)
135 char msgtext[sizeof(_trace.name)];
139 /* init trace with given values */
142 numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype, options.national, options.international),
146 ea_endpoint->ep_serial,
153 /* set new endpoint state
155 void EndpointAppPBX::new_state(int state)
158 if (e_state != state)
160 trace_header("NEW STATE", DIRECTION_NONE);
161 add_trace("state", "old", "%s", state_name[e_state]);
162 add_trace("state", "new", "%s", state_name[state]);
170 /* release join and port (as specified)
172 void EndpointAppPBX::release(int release, int joinlocation, int joincause, int portlocation, int portcause)
174 struct port_list *portlist;
175 struct lcr_msg *message;
178 /* message to test call */
179 admin_call_response(e_adminid, ADMIN_CALL_RELEASE, "", joincause, joinlocation, 0);
181 /* if a release is pending */
182 if (release==RELEASE_JOIN || release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY)
184 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): do pending release (joincause %d location %d)\n", ea_endpoint->ep_serial, joincause, joinlocation);
185 if (ea_endpoint->ep_join_id)
187 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_RELEASE);
188 message->param.disconnectinfo.cause = joincause;
189 message->param.disconnectinfo.location = joinlocation;
190 message_put(message);
191 ea_endpoint->ep_join_id = 0;
195 if (release != RELEASE_PORT_JOINONLY)
198 join_release(e_hold_id, ea_endpoint->ep_serial, 1, joinlocation, joincause);
203 if (release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY)
205 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release (portcause %d portlocation)\n", ea_endpoint->ep_serial, portcause, portlocation);
206 while((portlist = ea_endpoint->ep_portlist))
208 if (portlist->port_id)
210 SPRINT(cause, "cause_%02x", portcause);
211 set_tone(portlist, cause);
212 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
213 message->param.disconnectinfo.cause = portcause;
214 message->param.disconnectinfo.location = portlocation;
215 message_put(message);
216 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
218 ea_endpoint->free_portlist(portlist);
221 /* if callback is enabled, call back with the given caller id */
224 /* reset some stuff */
225 new_state(EPOINT_STATE_IDLE);
226 memset(&e_connectinfo, 0, sizeof(struct connect_info));
227 memset(&e_redirinfo, 0, sizeof(struct redir_info));
228 e_start = e_stop = 0;
229 e_ruleset = ruleset_main;
231 e_rule = e_ruleset->rule_first;
233 e_action_timeout = 0;
235 e_match_to_action = NULL;
237 e_extdialing = e_dialinginfo.id;
245 e_multipoint_cause = 0;
246 e_multipoint_location = 0;
247 e_dialing_queue[0] = '\0';
249 e_crypt_state = CM_ST_NULL;
250 e_crypt_keyengine_busy = 0;
251 e_crypt_info[0] = '\0';
255 e_tx_state = NOTIFY_STATE_ACTIVE;
256 e_rx_state = NOTIFY_STATE_ACTIVE;
257 e_join_cause = e_join_location = 0;
259 /* the caller info of the callback user */
260 memcpy(&e_callbackinfo, &e_callerinfo, sizeof(e_callbackinfo));
261 memset(&e_dialinginfo, 0, sizeof(e_dialinginfo));
262 /* create dialing by callerinfo */
263 if (e_ext.number[0] && e_extension_interface[0])
265 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to internal: %s interface %s\n", ea_endpoint->ep_serial, e_ext.number, e_extension_interface);
266 /* create callback to the current terminal */
267 SCPY(e_dialinginfo.id, e_ext.number);
268 SCPY(e_dialinginfo.interfaces, e_extension_interface);
269 e_dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
270 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
275 SCPY(e_dialinginfo.id, e_cbto);
278 /* numberrize caller id and use it to dial to the callback */
279 SCPY(e_dialinginfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype, options.national, options.international));
281 e_dialinginfo.itype = INFO_ITYPE_ISDN;
282 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
283 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to external: %s\n", ea_endpoint->ep_serial, e_dialinginfo.id);
288 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release of epoint itself.\n", ea_endpoint->ep_serial);
289 ea_endpoint->ep_use--; /* when e_lock is 0, the endpoint will be deleted */
295 /* cancel callerid if restricted, unless anon-ignore is enabled at extension or port is of type external (so called police gets caller id :)*/
296 void apply_callerid_restriction(struct extension *ext, char *id, int *ntype, int *present, int *screen, char *extension, char *name)
298 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");
300 /* caller id is not restricted, so we do nothing */
301 if (*present != INFO_PRESENT_RESTRICTED)
304 /* only extensions are restricted */
308 /* if we enabled anonymouse ignore */
309 if (ext->anon_ignore)
312 /* else we remove the caller id */
316 *ntype = INFO_NTYPE_UNKNOWN;
318 // *screen = INFO_SCREEN_USER;
319 // maybe we should not make voip address anonymous
322 // maybe it's no fraud to present extension id
324 // extension[0] = '\0';
329 /* used display message to display callerid as available */
330 char *EndpointAppPBX::apply_callerid_display(const char *id, int itype, int ntype, int present, int screen, const char *extension, const char *name)
332 static char display[81];
335 const char *cid = numberrize_callerinfo(id, ntype, options.national, options.international);
337 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");
346 /* NOTE: is caller is is not available for this extesion, it has been removed by apply_callerid_restriction already */
348 /* internal extension's caller id */
349 if (extension[0] && e_ext.display_int)
352 SCAT(display, extension);
355 if (itype == INFO_ITYPE_VBOX)
356 SCAT(display, "(vbox)");
358 SCAT(display, "(int)");
361 /* external caller id */
362 if (!extension[0] && e_ext.display_ext)
368 if (present == INFO_PRESENT_RESTRICTED)
369 SCAT(display, "anonymous");
371 SCAT(display, "unknown");
378 /* display if callerid is anonymouse but available due anon-ignore */
379 if (e_ext.display_anon && present==INFO_PRESENT_RESTRICTED)
382 SCAT(display, "unknown");
385 SCAT(display, " anon");
388 /* display if callerid is anonymouse but available due anon-ignore */
389 if (e_ext.display_fake && screen==INFO_SCREEN_USER && ntype!=INFO_NTYPE_NOTPRESENT)
395 if (present == INFO_PRESENT_RESTRICTED)
396 SCAT(display, "anonymous");
398 SCAT(display, "unknown");
403 SCAT(display, " fake");
407 if (name[0] && e_ext.display_name)
409 if (!display[0] && cid[0])
420 * uses the current state to notify activity
422 void EndpointAppPBX::notify_active(void)
424 struct port_list *portlist = ea_endpoint->ep_portlist;
425 struct lcr_msg *message;
430 case NOTIFY_STATE_ACTIVE:
431 /* we are already active, so we don't do anything */
434 case NOTIFY_STATE_SUSPEND:
435 notify = INFO_NOTIFY_USER_RESUMED;
438 set_tone(portlist, NULL);
439 portlist = portlist->next;
441 portlist = ea_endpoint->ep_portlist;
444 case NOTIFY_STATE_HOLD:
445 notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
448 set_tone(portlist, NULL);
449 portlist = portlist->next;
451 portlist = ea_endpoint->ep_portlist;
454 case NOTIFY_STATE_CONFERENCE:
455 notify = INFO_NOTIFY_CONFERENCE_DISCONNECTED;
458 set_tone(portlist, NULL);
459 portlist = portlist->next;
461 portlist = ea_endpoint->ep_portlist;
465 PERROR("unknown e_tx_state = %d\n", e_tx_state);
471 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
472 message->param.notifyinfo.notify = notify;
473 message_put(message);
474 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
475 portlist = portlist->next;
481 * keypad functions during call. one example to use this is to put a call on hold or start a conference
483 void EndpointAppPBX::keypad_function(char digit)
486 /* we must be in a call, in order to send messages to the call */
487 if (e_ext.number[0] == '\0')
489 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) IGNORING keypad received not from extension.\n", ea_endpoint->ep_serial);
495 /* join conference */
497 if (ea_endpoint->ep_join_id == 0)
499 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad received during connect but not during a call.\n", ea_endpoint->ep_serial);
502 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join call with call on hold\n", ea_endpoint->ep_serial);
508 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) shared key encryption selected.\n", ea_endpoint->ep_serial);
512 /* crypt key-exchange */
514 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) key exchange encryption selected.\n", ea_endpoint->ep_serial);
520 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) encryption off selected.\n", ea_endpoint->ep_serial);
525 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) unsupported keypad digit '%c'.\n", ea_endpoint->ep_serial, digit);
530 /* set tone pattern for port */
531 void EndpointAppPBX::set_tone(struct port_list *portlist, const char *tone)
533 struct lcr_msg *message;
538 /* store for suspended processes */
542 if (e_join_pattern /* pattern are provided */
543 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_SETUP)
544 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_OVERLAP)
545 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_IN_PROCEEDING)
546 && !(e_ext.own_alerting && e_state == EPOINT_STATE_IN_ALERTING)
547 && !(e_ext.own_cause && e_state == EPOINT_STATE_IN_DISCONNECT)
548 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_SETUP)
549 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_OVERLAP)
550 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_OUT_PROCEEDING)
551 && !(e_ext.own_alerting && e_state == EPOINT_STATE_OUT_ALERTING)
552 && !(e_ext.own_cause && e_state == EPOINT_STATE_OUT_DISCONNECT)
553 && tone[0] && !!strncmp(tone,"crypt_*",6))
555 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) tone not provided since patterns are available\n", ea_endpoint->ep_serial);
561 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_TONE);
562 SCPY(message->param.tone.dir, e_ext.tones_dir[0]?e_ext.tones_dir:options.tones_dir);
563 SCPY(message->param.tone.name, tone);
564 message_put(message);
565 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
568 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port to notify tone.\n", ea_endpoint->ep_serial);
575 * hunts an mISDNport that is available for an outgoing call
576 * if no ifname was given, any interface that is not an extension
579 struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel)
581 struct interface *interface;
582 struct interface_port *ifport, *ifport_start;
583 struct select_channel *selchannel;
584 struct mISDNport *mISDNport;
587 interface = interface_first;
589 /* first find the given interface or, if not given, one with no extension */
594 /* check for given interface */
597 if (!strcasecmp(interface->name, ifname))
599 /* found explicit interface */
600 trace_header("CHANNEL SELECTION (found interface)", DIRECTION_NONE);
601 add_trace("interface", NULL, "%s", ifname);
608 if (!interface->extension)
610 /* found non extension */
611 trace_header("CHANNEL SELECTION (found non extension interface)", DIRECTION_NONE);
612 add_trace("interface", NULL, "%s", interface->name);
618 interface = interface->next;
622 /* see if interface has ports */
623 if (!interface->ifport)
626 trace_header("CHANNEL SELECTION (active ports, skipping)", DIRECTION_NONE);
627 add_trace("interface", NULL, "%s", interface->name);
629 interface = interface->next;
633 /* select port by algorithm */
634 ifport_start = interface->ifport;
636 if (interface->hunt == HUNT_ROUNDROBIN)
638 while(ifport_start->next && index<interface->hunt_next)
640 ifport_start = ifport_start->next;
643 trace_header("CHANNEL SELECTION (starting round-robin)", DIRECTION_NONE);
644 add_trace("port", NULL, "%d", ifport_start->portnum);
645 add_trace("position", NULL, "%d", index);
650 ifport = ifport_start;
653 /* see if port is available */
654 if (!ifport->mISDNport)
656 trace_header("CHANNEL SELECTION (port not available, skipping)", DIRECTION_NONE);
657 add_trace("port", NULL, "%d", ifport->portnum);
658 add_trace("position", NULL, "%d", index);
662 mISDNport = ifport->mISDNport;
664 /* see if port is administratively blocked */
667 trace_header("CHANNEL SELECTION (port blocked by admin, skipping)", DIRECTION_NONE);
668 add_trace("port", NULL, "%d", ifport->portnum);
669 add_trace("position", NULL, "%d", index);
674 /* see if link is up on PTP*/
675 if (mISDNport->l2hold && mISDNport->l2link<1)
677 trace_header("CHANNEL SELECTION (port's layer 2 is down, skipping)", DIRECTION_NONE);
678 add_trace("port", NULL, "%d", ifport->portnum);
679 add_trace("position", NULL, "%d", index);
684 /* check for channel form selection list */
686 selchannel = ifport->out_channel;
689 switch(selchannel->channel)
691 case CHANNEL_FREE: /* free channel */
692 if (mISDNport->b_reserved >= mISDNport->b_num)
693 break; /* all channel in use or reserverd */
696 while(i < mISDNport->b_num)
698 if (mISDNport->b_port[i] == NULL)
700 *channel = i+1+(i>=15);
701 trace_header("CHANNEL SELECTION (selecting free channel)", DIRECTION_NONE);
702 add_trace("port", NULL, "%d", ifport->portnum);
703 add_trace("position", NULL, "%d", index);
704 add_trace("channel", NULL, "%d", *channel);
712 trace_header("CHANNEL SELECTION (no channel is 'free')", DIRECTION_NONE);
713 add_trace("port", NULL, "%d", ifport->portnum);
714 add_trace("position", NULL, "%d", index);
718 case CHANNEL_ANY: /* don't ask for channel */
719 if (mISDNport->b_reserved >= mISDNport->b_num)
721 trace_header("CHANNEL SELECTION (cannot ask for 'any' channel, all reserved)", DIRECTION_NONE);
722 add_trace("port", NULL, "%d", ifport->portnum);
723 add_trace("position", NULL, "%d", index);
724 add_trace("total", NULL, "%d", mISDNport->b_num);
725 add_trace("reserved", NULL, "%d", mISDNport->b_reserved);
727 break; /* all channel in use or reserverd */
729 trace_header("CHANNEL SELECTION (using 'any' channel)", DIRECTION_NONE);
730 add_trace("port", NULL, "%d", ifport->portnum);
731 add_trace("position", NULL, "%d", index);
733 *channel = CHANNEL_ANY;
736 case CHANNEL_NO: /* call waiting */
737 trace_header("CHANNEL SELECTION (using 'no' channel, call-waiting)", DIRECTION_NONE);
738 add_trace("port", NULL, "%d", ifport->portnum);
739 add_trace("position", NULL, "%d", index);
741 *channel = CHANNEL_NO;
745 if (selchannel->channel<1 || selchannel->channel==16)
747 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
748 add_trace("port", NULL, "%d", ifport->portnum);
749 add_trace("position", NULL, "%d", index);
750 add_trace("channel", NULL, "%d", selchannel->channel);
752 break; /* invalid channels */
754 i = selchannel->channel-1-(selchannel->channel>=17);
755 if (i >= mISDNport->b_num)
757 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
758 add_trace("port", NULL, "%d", ifport->portnum);
759 add_trace("position", NULL, "%d", index);
760 add_trace("channel", NULL, "%d", selchannel->channel);
761 add_trace("channels", NULL, "%d", mISDNport->b_num);
763 break; /* channel not in port */
765 if (mISDNport->b_port[i] == NULL)
767 *channel = selchannel->channel;
768 trace_header("CHANNEL SELECTION (selecting given channel)", DIRECTION_NONE);
769 add_trace("port", NULL, "%d", ifport->portnum);
770 add_trace("position", NULL, "%d", index);
771 add_trace("channel", NULL, "%d", *channel);
778 break; /* found channel */
779 selchannel = selchannel->next;
782 /* if channel was found, return mISDNport and channel */
785 /* setting next port to start next time */
786 if (interface->hunt == HUNT_ROUNDROBIN)
791 interface->hunt_next = index;
797 trace_header("CHANNEL SELECTION (skipping, no channel found)", DIRECTION_NONE);
798 add_trace("port", NULL, "%d", ifport->portnum);
799 add_trace("position", NULL, "%d", index);
803 /* go next port, until all ports are checked */
805 ifport = ifport->next;
809 ifport = interface->ifport;
811 if (ifport != ifport_start)
815 interface = interface->next;
819 return(NULL); /* no port found */
822 /* outgoing setup to port(s)
823 * ports will be created and a setup is sent if everything is ok. otherwhise
824 * the endpoint is destroyed.
826 void EndpointAppPBX::out_setup(void)
828 struct dialing_info dialinginfo;
830 struct port_list *portlist;
831 struct lcr_msg *message;
833 int cause = CAUSE_RESSOURCEUNAVAIL;
836 struct mISDNport *mISDNport;
839 class EndpointAppPBX *atemp;
840 // char allowed_ports[256];
842 char ifname[sizeof(e_ext.interfaces)],
844 struct port_settings port_settings;
847 int mode = B_MODE_TRANSPARENT;
849 /* set bchannel mode */
850 mode = e_capainfo.source_mode;
852 /* create settings for creating port */
853 memset(&port_settings, 0, sizeof(port_settings));
855 SCPY(port_settings.tones_dir, e_ext.tones_dir);
857 SCPY(port_settings.tones_dir, options.tones_dir);
858 port_settings.no_seconds = e_ext.no_seconds;
860 /* 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 */
862 /* check what dialinginfo.itype we got */
863 switch(e_dialinginfo.itype)
865 /* *********************** call to extension or vbox */
866 case INFO_ITYPE_ISDN_EXTENSION:
867 /* check if we deny incoming calls when we use an extension */
868 if (e_ext.noknocking)
870 atemp = apppbx_first;
874 if (!strcmp(atemp->e_ext.number, e_ext.number))
880 PERROR("EPOINT(%d) noknocking and currently a call\n", ea_endpoint->ep_serial);
881 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYSPE_ join, port */
882 return; /* must exit here */
885 /* FALL THROUGH !!!! */
886 case INFO_ITYPE_VBOX:
887 /* get dialed extension's info */
888 // SCPY(exten, e_dialinginfo.id);
889 // if (strchr(exten, ','))
890 // *strchr(exten, ',') = '\0';
891 // if (!read_extension(&e_ext, exten))
892 if (!read_extension(&e_ext, e_dialinginfo.id))
894 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) extension %s not configured\n", ea_endpoint->ep_serial, e_dialinginfo.id);
895 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
896 return; /* must exit here */
899 if (e_dialinginfo.itype == INFO_ITYPE_VBOX)
901 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing directly to VBOX\n", ea_endpoint->ep_serial);
906 /* string from unconditional call forward (cfu) */
910 /* present to forwarded party */
911 if (e_ext.anon_ignore && e_callerinfo.id[0])
913 e_callerinfo.present = INFO_PRESENT_ALLOWED;
915 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
919 /* string from busy call forward (cfb) */
923 class EndpointAppPBX *checkapp = apppbx_first;
926 if (checkapp != this) /* any other endpoint except our own */
928 if (!strcmp(checkapp->e_ext.number, e_ext.number))
930 /* present to forwarded party */
931 if (e_ext.anon_ignore && e_callerinfo.id[0])
933 e_callerinfo.present = INFO_PRESENT_ALLOWED;
935 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
939 checkapp = checkapp->next;
943 /* string from no-response call forward (cfnr) */
947 /* when cfnr is done, out_setup() will setup the call */
950 /* present to forwarded party */
951 if (e_ext.anon_ignore && e_callerinfo.id[0])
953 e_callerinfo.present = INFO_PRESENT_ALLOWED;
957 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
959 e_cfnr_release = now + e_ext.cfnr_delay;
960 e_cfnr_call = now + e_ext.cfnr_delay + 1; /* call one second after release */
961 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);
965 /* call to all internal interfaces */
966 p = e_ext.interfaces;
967 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) generating multiple joins for extension %s to interfaces %s\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
971 while(*p!=',' && *p!='\0')
976 /* found interface */
977 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
978 /* hunt for mISDNport and create Port */
979 mISDNport = hunt_port(ifname, &channel);
982 trace_header("INTERFACE (not found or busy)", DIRECTION_NONE);
983 add_trace("interface", NULL, "%s", ifname);
987 /* creating INTERNAL port */
988 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
990 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);
993 port = new Pgsm(PORT_TYPE_GSM_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
998 FATAL("No memory for Port instance\n");
999 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
1000 memset(&dialinginfo, 0, sizeof(dialinginfo));
1001 SCPY(dialinginfo.id, e_dialinginfo.id);
1002 dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
1003 dialinginfo.ntype = e_dialinginfo.ntype;
1004 /* create port_list relation */
1005 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
1008 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1010 goto check_anycall_intern;
1012 /* directory.list */
1013 if (e_callerinfo.id[0] && e_ext.display_name)
1015 dirname = parse_directory(e_callerinfo.id, e_callerinfo.ntype);
1017 SCPY(e_callerinfo.name, dirname);
1019 // dss1 = (class Pdss1 *)port;
1021 //printf("INTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1022 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1023 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1024 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1025 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1026 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1027 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1028 //terminal if (e_dialinginfo.id)
1029 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1030 /* handle restricted caller ids */
1031 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);
1032 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);
1033 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);
1034 /* display callerid if desired for extension */
1035 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));
1036 //printf("\n\ndisplay = %s\n\n\n",message->param.setup.callerinfo.display);
1037 /* use cnip, if enabld */
1038 // if (!e_ext.centrex)
1039 // message->param.setup.callerinfo.name[0] = '\0';
1040 /* screen clip if prefix is required */
1041 if (message->param.setup.callerinfo.id[0] && e_ext.clip_prefix[0])
1043 SCPY(message->param.setup.callerinfo.id, e_ext.clip_prefix);
1044 SCAT(message->param.setup.callerinfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype, options.national, options.international));
1045 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1047 if (message->param.setup.callerinfo.id2[0] && e_ext.clip_prefix[0])
1049 SCPY(message->param.setup.callerinfo.id2, e_ext.clip_prefix);
1050 SCAT(message->param.setup.callerinfo.id2, numberrize_callerinfo(e_callerinfo.id2,e_callerinfo.ntype2, options.national, options.international));
1051 message->param.setup.callerinfo.ntype2 = INFO_NTYPE_UNKNOWN;
1053 /* use internal caller id */
1054 if (e_callerinfo.extension[0] && (message->param.setup.callerinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
1056 SCPY(message->param.setup.callerinfo.id, e_callerinfo.extension);
1057 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1058 message->param.setup.callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
1060 message_put(message);
1061 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1065 /* string from parallel call forward (cfp) */
1069 if (e_ext.anon_ignore && e_callerinfo.id[0])
1071 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1072 e_callerinfo.present2 = INFO_PRESENT_ALLOWED;
1076 vbox_only: /* entry point for answering machine only */
1077 cfu_only: /* entry point for cfu */
1078 cfb_only: /* entry point for cfb */
1079 cfnr_only: /* entry point for cfnr */
1080 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call extension %s for external destiantion(s) '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
1085 /* only if vbox should be dialed, and terminal is given */
1086 if (!strcmp(p, "vbox") && e_ext.number[0])
1088 /* go to the end of p */
1091 /* answering vbox call */
1092 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) answering machine\n", ea_endpoint->ep_serial);
1094 if (!(port = new VBoxPort(PORT_TYPE_VBOX_OUT, &port_settings)))
1095 FATAL("No memory for VBOX Port instance\n");
1096 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocated port %s\n", ea_endpoint->ep_serial, port->p_name);
1097 UCPY(cfp, e_ext.number); /* cfp or any other direct forward/vbox */
1101 while(*p!=',' && *p!='\0')
1106 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cfp external %s\n", ea_endpoint->ep_serial, cfp);
1107 /* hunt for mISDNport and create Port */
1108 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1111 /* creating EXTERNAL port*/
1112 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1113 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);
1115 FATAL("No memory for Port instance\n");
1116 earlyb = mISDNport->earlyb;
1120 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1121 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1127 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port found or created, which is idle.\n", ea_endpoint->ep_serial);
1128 goto check_anycall_intern;
1130 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found or created port %s\n", ea_endpoint->ep_serial, port->p_name);
1131 memset(&dialinginfo, 0, sizeof(dialinginfo));
1132 SCPY(dialinginfo.id, cfp);
1133 dialinginfo.itype = INFO_ITYPE_ISDN;
1134 dialinginfo.ntype = e_dialinginfo.ntype;
1135 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
1138 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1140 goto check_anycall_intern;
1142 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1143 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1144 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
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 /* if clip is hidden */
1148 if (e_ext.clip==CLIP_HIDE && port->p_type!=PORT_TYPE_VBOX_OUT)
1150 SCPY(message->param.setup.callerinfo.id, e_ext.callerid);
1151 SCPY(message->param.setup.callerinfo.extension, e_ext.number);
1152 message->param.setup.callerinfo.ntype = e_ext.callerid_type;
1153 message->param.setup.callerinfo.present = e_ext.callerid_present;
1154 message->param.setup.callerinfo.ntype = INFO_NTYPE_NOTPRESENT;
1156 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1157 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1158 //terminal if (e_dialinginfo.id)
1159 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1160 /* handle restricted caller ids */
1161 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);
1162 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);
1163 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);
1164 /* display callerid if desired for extension */
1165 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));
1166 message_put(message);
1167 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1171 check_anycall_intern:
1172 /* now we have all ports created */
1175 trace_header("INTERFACE (no extension's interface)", DIRECTION_NONE);
1177 if (!ea_endpoint->ep_join_id)
1179 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1180 return; /* must exit here */
1184 /* *********************** external call */
1186 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id);
1187 /* call to extenal interfaces */
1188 p = e_dialinginfo.id;
1192 while(*p!=',' && *p!='\0')
1193 SCCAT(number, *p++);
1197 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");
1198 /* hunt for mISDNport and create Port */
1199 /* hunt for mISDNport and create Port */
1200 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1203 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1204 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1206 goto check_anycall_extern;
1208 /* creating EXTERNAL port*/
1209 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1210 if (!mISDNport->gsm)
1211 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
1214 port = new Pgsm(PORT_TYPE_GSM_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
1219 FATAL("No memory for Port instance\n");
1220 earlyb = mISDNport->earlyb;
1221 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
1222 memset(&dialinginfo, 0, sizeof(dialinginfo));
1223 SCPY(dialinginfo.id, number);
1224 dialinginfo.itype = INFO_ITYPE_ISDN;
1225 dialinginfo.ntype = e_dialinginfo.ntype;
1226 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
1229 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1231 goto check_anycall_extern;
1233 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1234 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1235 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1236 SCPY(message->param.setup.dialinginfo.id, number);
1237 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1238 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1239 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1240 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1241 //terminal if (e_dialinginfo.id)
1242 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1243 /* handle restricted caller ids */
1244 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);
1245 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);
1246 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);
1247 /* display callerid if desired for extension */
1248 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));
1249 message_put(message);
1250 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1254 check_anycall_extern:
1255 /* now we have all ports created */
1258 trace_header("INTERFACE (no free ports found)", DIRECTION_NONE);
1260 if (!ea_endpoint->ep_join_id)
1262 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1263 return; /* must exit here */
1271 /* handler for endpoint
1275 int EndpointAppPBX::handler(void)
1277 if (e_crypt_state!=CM_ST_NULL)
1282 /* process answering machine (play) handling */
1285 if (e_action->index == ACTION_VBOX_PLAY)
1288 /* process action timeout */
1289 if (e_action_timeout)
1290 if (now_d >= e_action_timeout)
1292 if (e_state!=EPOINT_STATE_CONNECT)
1295 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current action timed out.\n", ea_endpoint->ep_serial);
1296 e_multipoint_cause = 0;
1297 e_multipoint_location = 0;
1298 new_state(EPOINT_STATE_IN_OVERLAP);
1301 return(1); /* we must exit, because our endpoint might be gone */
1303 e_action_timeout = 0;
1306 /* process action timeout */
1307 if (e_match_timeout)
1308 if (now_d >= e_match_timeout)
1311 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we got a match timeout.\n", ea_endpoint->ep_serial);
1313 return(1); /* we must exit, because our endpoint might be gone */
1318 /* process redialing (epoint redials to port) */
1321 if (now_d >= e_redial)
1324 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial.\n", ea_endpoint->ep_serial);
1326 new_state(EPOINT_STATE_OUT_SETUP);
1327 /* call special setup routine */
1334 /* process powerdialing (epoint redials to epoint) */
1335 if (e_powerdialing > 0)
1337 if (now_d >= e_powerdialing)
1339 e_powerdialing = -1; /* leave power dialing on */
1340 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial of powerdial.\n", ea_endpoint->ep_serial);
1343 e_ruleset = ruleset_main;
1345 e_rule = e_ruleset->rule_first;
1347 new_state(EPOINT_STATE_IN_OVERLAP);
1353 /* process call forward no response */
1356 struct port_list *portlist;
1357 struct lcr_msg *message;
1359 if (now >= e_cfnr_release)
1361 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-no-response time has expired, hanging up.\n", ea_endpoint->ep_serial);
1364 /* release all ports */
1365 while((portlist = ea_endpoint->ep_portlist))
1367 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1368 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
1369 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1370 message_put(message);
1371 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1372 ea_endpoint->free_portlist(portlist);
1375 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1376 message->param.audiopath = 0;
1377 message_put(message);
1378 /* indicate no patterns */
1379 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1380 message_put(message);
1381 /* set setup state, since we have no response from the new join */
1382 new_state(EPOINT_STATE_OUT_SETUP);
1387 if (now >= e_cfnr_call)
1389 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-busy time has expired, calling the forwarded number: %s.\n", ea_endpoint->ep_serial, e_ext.cfnr);
1395 /* handle connection to user */
1396 if (e_state == EPOINT_STATE_IDLE)
1398 /* epoint is idle, check callback */
1400 if (now_d >= e_callback)
1402 e_callback = 0; /* done with callback */
1403 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting callback.\n", ea_endpoint->ep_serial);
1404 new_state(EPOINT_STATE_OUT_SETUP);
1410 /* check for password timeout */
1412 if (e_action->index==ACTION_PASSWORD || e_action->index==ACTION_PASSWORD_WRITE)
1414 struct port_list *portlist;
1416 if (now >= e_password_timeout)
1418 e_ruleset = ruleset_main;
1420 e_rule = e_ruleset->rule_first;
1422 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) password timeout %s\n", ea_endpoint->ep_serial, e_extdialing);
1423 trace_header("PASSWORD timeout", DIRECTION_NONE);
1425 e_connectedmode = 0;
1427 new_state(EPOINT_STATE_OUT_DISCONNECT);
1428 portlist = ea_endpoint->ep_portlist;
1431 message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
1432 set_tone(portlist, "cause_10");
1442 /* doing a hookflash */
1443 void EndpointAppPBX::hookflash(void)
1447 /* be sure that we are active */
1449 e_tx_state = NOTIFY_STATE_ACTIVE;
1451 trace_header("HOOKFLASH DTMF", DIRECTION_NONE);
1453 if (ea_endpoint->ep_use > 1)
1455 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot hooflash while child process is running.\n", ea_endpoint->ep_serial);
1458 /* dialtone after pressing the hash key */
1459 process_hangup(e_join_cause, e_join_location);
1460 e_multipoint_cause = 0;
1461 e_multipoint_location = 0;
1462 port = find_port_id(ea_endpoint->ep_portlist->port_id);
1465 port->set_echotest(0);
1467 if (ea_endpoint->ep_join_id)
1469 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1471 e_ruleset = ruleset_main;
1473 e_rule = e_ruleset->rule_first;
1475 new_state(EPOINT_STATE_IN_OVERLAP);
1476 e_connectedmode = 1;
1477 SCPY(e_dialinginfo.id, e_ext.prefix);
1478 e_extdialing = e_dialinginfo.id;
1480 if (e_dialinginfo.id[0])
1482 set_tone(ea_endpoint->ep_portlist, "dialing");
1486 set_tone(ea_endpoint->ep_portlist, "dialpbx");
1493 /* messages from port
1495 /* port MESSAGE_SETUP */
1496 void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, union parameter *param)
1498 struct lcr_msg *message;
1500 int writeext; /* flags need to write extension after modification */
1502 struct interface *interface;
1504 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1506 portlist->port_type = param->setup.port_type;
1507 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
1508 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
1509 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
1510 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
1511 // e_dtmf = param->setup.dtmf;
1512 /* screen incoming caller id */
1513 interface = interface_first;
1516 if (!strcmp(e_callerinfo.interface, interface->name))
1520 interface = interface->next;
1523 do_screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface);
1524 do_screen(0, e_callerinfo.id2, sizeof(e_callerinfo.id2), &e_callerinfo.ntype2, &e_callerinfo.present2, interface);
1527 /* process extension */
1528 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1530 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is extension\n", ea_endpoint->ep_serial);
1531 /* port makes call from extension */
1532 SCPY(e_callerinfo.extension, e_callerinfo.id);
1533 SCPY(e_ext.number, e_callerinfo.extension);
1534 SCPY(e_extension_interface, e_callerinfo.interface);
1537 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is external or voip\n", ea_endpoint->ep_serial);
1540 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1542 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1544 /* get extension's info about caller */
1545 if (!read_extension(&e_ext, e_ext.number))
1547 /* extension doesn't exist */
1548 trace_header("EXTENSION (not created)", DIRECTION_IN);
1549 add_trace("extension", NULL, "%s", e_ext.number);
1551 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
1552 new_state(EPOINT_STATE_OUT_DISCONNECT);
1553 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
1554 e_ext.number[0] = '\0'; /* no terminal */
1559 /* put prefix (next) in front of e_dialinginfo.id */
1562 SPRINT(buffer, "%s%s", e_ext.next, e_dialinginfo.id);
1563 SCPY(e_dialinginfo.id, buffer);
1564 e_ext.next[0] = '\0';
1566 } else if (e_ext.prefix[0])
1568 SPRINT(buffer, "%s%s", e_ext.prefix, e_dialinginfo.id);
1569 SCPY(e_dialinginfo.id, buffer);
1572 /* screen caller id by extension's config */
1573 e_callerinfo.screen = INFO_SCREEN_NETWORK;
1575 SCPY(e_callerinfo.name, e_ext.name);
1576 /* use caller id (or if exist: id_next_call) for this call */
1577 if (e_ext.id_next_call_present >= 0)
1579 SCPY(e_callerinfo.id, e_ext.id_next_call);
1580 /* if we restrict the pesentation */
1581 if (e_ext.id_next_call_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1582 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1583 else e_callerinfo.present = e_ext.id_next_call_present;
1584 e_callerinfo.ntype = e_ext.id_next_call_type;
1585 e_ext.id_next_call_present = -1;
1589 SCPY(e_callerinfo.id, e_ext.callerid);
1590 /* if we restrict the pesentation */
1591 if (e_ext.callerid_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1592 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1593 else e_callerinfo.present = e_ext.callerid_present;
1594 e_callerinfo.ntype = e_ext.callerid_type;
1596 e_callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
1598 /* extension is written */
1600 write_extension(&e_ext, e_ext.number);
1602 /* set volume of rx and tx */
1603 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1604 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
1606 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
1607 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
1608 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
1609 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
1610 message_put(message);
1613 /* start recording if enabled */
1614 if (e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO))
1616 /* check if we are a terminal */
1617 if (e_ext.number[0] == '\0')
1618 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
1621 port = find_port_id(portlist->port_id);
1623 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
1628 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from external port\n", ea_endpoint->ep_serial);
1629 /* no terminal identification */
1630 e_ext.number[0] = '\0';
1631 e_extension_interface[0] = '\0';
1632 memset(&e_ext, 0, sizeof(e_ext));
1633 e_ext.rights = 4; /* right to dial internat */
1637 e_ruleset = ruleset_main;
1639 e_rule = e_ruleset->rule_first;
1641 e_extdialing = e_dialinginfo.id;
1642 new_state(EPOINT_STATE_IN_SETUP);
1643 if (e_dialinginfo.id[0])
1645 set_tone(portlist, "dialing");
1648 if (e_ext.number[0])
1649 set_tone(portlist, "dialpbx");
1651 set_tone(portlist, "dialtone");
1654 if (e_state == EPOINT_STATE_IN_SETUP)
1656 /* request MORE info, if not already at higher state */
1657 new_state(EPOINT_STATE_IN_OVERLAP);
1658 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_OVERLAP);
1659 message_put(message);
1660 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1664 /* port MESSAGE_INFORMATION */
1665 void EndpointAppPBX::port_information(struct port_list *portlist, int message_type, union parameter *param)
1667 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1669 /* ignore information message without digit information */
1670 if (!param->information.id[0])
1675 /* turn off dtmf detection, in case dtmf is sent with keypad information */
1678 trace_header("DTMF (disabling due to keypad)", DIRECTION_IN);
1683 /* if vbox_play is done, the information are just used as they come */
1685 if (e_action->index == ACTION_VBOX_PLAY)
1687 /* concat dialing string */
1688 SCAT(e_dialinginfo.id, param->information.id);
1693 /* keypad when disconnect but in connected mode */
1694 if (e_state==EPOINT_STATE_OUT_DISCONNECT && e_connectedmode)
1696 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received after disconnect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1697 /* processing keypad function */
1698 if (param->information.id[0] == '0')
1705 /* keypad when connected */
1706 if (e_state == EPOINT_STATE_CONNECT)
1708 if (e_ext.keypad || e_enablekeypad)
1710 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1711 /* processing keypad function */
1712 if (param->information.id[0] == '0')
1716 if (param->information.id[0])
1717 keypad_function(param->information.id[0]);
1720 if (e_ext.number[0])
1721 trace_header("KEYPAD (not enabled by extension's settings)", DIRECTION_IN);
1723 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1728 if (e_state != EPOINT_STATE_IN_OVERLAP)
1730 if (e_ext.number[0])
1731 trace_header("KEYPAD (ignored, not connected and not dialing)", DIRECTION_IN);
1733 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1737 if (!param->information.id[0])
1739 if (e_dialinginfo.id[0]=='\0' && !e_action)
1741 set_tone(portlist, "dialing");
1744 if (e_action->index==ACTION_OUTDIAL
1745 || e_action->index==ACTION_EXTERNAL
1746 || e_action->index==ACTION_REMOTE)
1749 set_tone(portlist, "dialing");
1750 else if (!e_extdialing[0])
1751 set_tone(portlist, "dialing");
1753 /* concat dialing string */
1754 SCAT(e_dialinginfo.id, param->information.id);
1758 /* port MESSAGE_DTMF */
1759 void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
1761 /* only if dtmf detection is enabled */
1764 trace_header("DTMF (disabled)", DIRECTION_IN);
1768 trace_header("DTMF", DIRECTION_IN);
1769 add_trace("digit", NULL, "%c", param->dtmf);
1773 NOTE: vbox is now handled due to overlap state
1774 /* if vbox_play is done, the dtmf digits are just used as they come */
1776 if (e_action->index == ACTION_VBOX_PLAY)
1778 /* concat dialing string */
1779 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id))
1781 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1782 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1785 /* continue to process *X# sequences */
1789 /* check for *X# sequence */
1790 if (e_state == EPOINT_STATE_CONNECT)
1792 if (e_dtmf_time+3 < now)
1794 /* the last digit was too far in the past to be a sequence */
1795 if (param->dtmf == '*')
1796 /* only start is allowed in the sequence */
1802 /* we have a sequence of digits, see what we got */
1803 if (param->dtmf == '*')
1805 else if (param->dtmf>='0' && param->dtmf<='9')
1807 /* we need to have a star before we receive the digit of the sequence */
1808 if (e_dtmf_last == '*')
1809 e_dtmf_last = param->dtmf;
1810 } else if (param->dtmf == '#')
1813 if (e_dtmf_last>='0' && e_dtmf_last<='9')
1815 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf sequence *%c# detected.\n", ea_endpoint->ep_serial, e_dtmf_last);
1816 if (e_dtmf_last == '0')
1821 /* processing keypad function */
1823 keypad_function(e_dtmf_last);
1829 /* set last time of dtmf */
1834 /* check for ## hookflash during dialing */
1836 if (e_action->index==ACTION_PASSWORD
1837 || e_action->index==ACTION_PASSWORD_WRITE)
1839 if (param->dtmf=='#') /* current digit is '#' */
1841 if (e_state==EPOINT_STATE_IN_DISCONNECT
1842 || (e_state!=EPOINT_STATE_CONNECT && e_dtmf_time+3>=now && e_dtmf_last=='#')) /* when disconnected, just #. when dialing, ##. */
1859 /* dialing using dtmf digit */
1860 if (e_state==EPOINT_STATE_IN_OVERLAP)// && e_state==e_connectedmode)
1862 if (e_dialinginfo.id[0]=='\0' && !e_action)
1864 set_tone(portlist, "dialing");
1866 /* concat dialing string */
1867 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id))
1869 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1870 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1876 /* port MESSAGE_CRYPT */
1877 void EndpointAppPBX::port_crypt(struct port_list *portlist, int message_type, union parameter *param)
1879 /* send crypt response to cryptman */
1880 if (param->crypt.type == CR_MESSAGE_IND)
1881 cryptman_msg2man(param->crypt.data, param->crypt.len);
1883 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
1886 /* port MESSAGE_OVERLAP */
1887 void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, union parameter *param)
1889 struct lcr_msg *message;
1891 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1893 /* signal to call tool */
1894 admin_call_response(e_adminid, ADMIN_CALL_SETUP_ACK, "", 0, 0, 0);
1896 if (e_dialing_queue[0] && portlist)
1898 /* send what we have not dialed yet, because we had no setup complete */
1899 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing pending digits: '%s'\n", ea_endpoint->ep_serial, e_dialing_queue);
1900 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
1901 SCPY(message->param.information.id, e_dialing_queue);
1902 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
1903 message_put(message);
1904 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
1905 e_dialing_queue[0] = '\0';
1907 /* check if pattern is available */
1908 if (!ea_endpoint->ep_portlist->next && portlist->early_b) /* one port_list relation and tones available */
1910 /* indicate patterns */
1911 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1912 message_put(message);
1914 /* connect audio, if not already */
1915 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1916 message->param.audiopath = 1;
1917 message_put(message);
1920 /* indicate no patterns */
1921 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1922 message_put(message);
1924 /* disconnect audio, if not already */
1925 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1926 message->param.audiopath = 0;
1927 message_put(message);
1929 new_state(EPOINT_STATE_OUT_OVERLAP);
1930 /* if we are in a join */
1931 if (ea_endpoint->ep_join_id)
1933 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1934 memcpy(&message->param, param, sizeof(union parameter));
1935 message_put(message);
1939 /* port MESSAGE_PROCEEDING */
1940 void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_type, union parameter *param)
1942 struct lcr_msg *message;
1944 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1946 /* signal to call tool */
1947 admin_call_response(e_adminid, ADMIN_CALL_PROCEEDING, "", 0, 0, 0);
1949 e_state = EPOINT_STATE_OUT_PROCEEDING;
1950 /* check if pattern is availatle */
1951 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
1953 /* indicate patterns */
1954 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1955 message_put(message);
1957 /* connect audio, if not already */
1958 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1959 message->param.audiopath = 1;
1960 message_put(message);
1963 /* indicate no patterns */
1964 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1965 message_put(message);
1967 /* disconnect audio, if not already */
1968 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1969 message->param.audiopath = 0;
1970 message_put(message);
1972 /* if we are in a call */
1973 if (ea_endpoint->ep_join_id)
1975 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1976 memcpy(&message->param, param, sizeof(union parameter));
1977 message_put(message);
1981 /* port MESSAGE_ALERTING */
1982 void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type, union parameter *param)
1984 struct lcr_msg *message;
1986 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1988 /* signal to call tool */
1989 admin_call_response(e_adminid, ADMIN_CALL_ALERTING, "", 0, 0, 0);
1992 // set_tone(portlist, "hold");
1994 new_state(EPOINT_STATE_OUT_ALERTING);
1995 /* check if pattern is available */
1996 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
1998 /* indicate patterns */
1999 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2000 message_put(message);
2002 /* connect audio, if not already */
2003 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2004 message->param.audiopath = 1;
2005 message_put(message);
2008 /* indicate no patterns */
2009 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
2010 message_put(message);
2012 /* disconnect audio, if not already */
2013 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2014 message->param.audiopath = 0;
2015 message_put(message);
2017 /* if we are in a call */
2018 if (ea_endpoint->ep_join_id)
2020 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2021 memcpy(&message->param, param, sizeof(union parameter));
2022 message_put(message);
2026 /* port MESSAGE_CONNECT */
2027 void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, union parameter *param)
2029 struct lcr_msg *message;
2031 unsigned int port_id = portlist->port_id;
2032 struct port_list *tportlist;
2034 struct interface *interface;
2036 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2038 /* signal to call tool */
2039 admin_call_response(e_adminid, ADMIN_CALL_CONNECT, numberrize_callerinfo(param->connectinfo.id,param->connectinfo.ntype, options.national, options.international), 0, 0, 0);
2041 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_connectinfo));
2042 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (start)\n", ea_endpoint->ep_serial);
2043 while(ea_endpoint->ep_portlist->next) /* as long as we have at least two ports */
2045 tportlist = ea_endpoint->ep_portlist;
2046 if (tportlist->port_id == port_id) /* if the first portlist is the calling one, the second must be a different one */
2047 tportlist = tportlist->next;
2048 if (tportlist->port_id == port_id)
2049 FATAL("EPOINT(%d) this should not happen since the portlist list must not have two links to the same port - exitting.\n");
2050 message = message_create(ea_endpoint->ep_serial, tportlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2051 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
2052 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2053 message_put(message);
2054 logmessage(message->type, &message->param, tportlist->port_id, DIRECTION_OUT);
2055 ea_endpoint->free_portlist(tportlist);
2057 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (end)\n", ea_endpoint->ep_serial);
2061 /* screen incoming connected id */
2062 interface = interface_first;
2065 if (!strcmp(e_connectinfo.interface, interface->name))
2069 interface = interface->next;
2072 do_screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface);
2074 /* screen connected name */
2076 SCPY(e_connectinfo.name, e_ext.name);
2078 /* add internal id to colp */
2079 SCPY(e_connectinfo.extension, e_ext.number);
2081 /* we store the connected port number */
2082 SCPY(e_extension_interface, e_connectinfo.interface);
2084 /* for internal and am calls, we get the extension's id */
2085 if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE)
2087 SCPY(e_connectinfo.id, e_ext.callerid);
2088 SCPY(e_connectinfo.extension, e_ext.number);
2089 e_connectinfo.itype = INFO_ITYPE_ISDN_EXTENSION;
2090 e_connectinfo.ntype = e_ext.callerid_type;
2091 e_connectinfo.present = e_ext.callerid_present;
2093 if (portlist->port_type==PORT_TYPE_VBOX_OUT)
2095 e_connectinfo.itype = INFO_ITYPE_VBOX;
2096 e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2099 new_state(EPOINT_STATE_CONNECT);
2101 /* set volume of rx and tx */
2102 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
2104 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2105 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2106 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
2107 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
2108 message_put(message);
2111 e_cfnr_call = e_cfnr_release = 0;
2112 if (e_ext.number[0])
2113 e_dtmf = 1; /* allow dtmf */
2116 /* other calls with no caller id (or not available for the extension) and force colp */
2117 if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE)
2119 e_connectinfo.ntype = INFO_NTYPE_NOTPRESENT;
2120 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 */
2122 port = find_port_id(portlist->port_id);
2125 SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.id, &e_connectinfo.ntype, options.national, options.international));
2126 e_connectinfo.present = INFO_PRESENT_ALLOWED;
2131 /* send connect to join */
2132 if (ea_endpoint->ep_join_id)
2134 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2135 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
2136 message_put(message);
2138 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2139 message->param.audiopath = 1;
2140 message_put(message);
2141 } else if (!e_adminid)
2144 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have a callback, so we create a call with cbcaller: \"%s\".\n", ea_endpoint->ep_serial, e_cbcaller);
2145 SCPY(e_ext.number, e_cbcaller);
2146 new_state(EPOINT_STATE_IN_OVERLAP);
2147 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) callback from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2149 /* get extension's info about terminal */
2150 if (!read_extension(&e_ext, e_ext.number))
2152 /* extension doesn't exist */
2153 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2154 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
2155 new_state(EPOINT_STATE_OUT_DISCONNECT);
2156 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
2160 /* put prefix in front of e_cbdialing */
2161 SPRINT(buffer, "%s%s", e_ext.prefix, e_cbdialing);
2162 SCPY(e_dialinginfo.id, buffer);
2163 e_dialinginfo.itype = INFO_ITYPE_ISDN;
2164 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
2166 /* use caller id (or if exist: id_next_call) for this call */
2167 e_callerinfo.screen = INFO_SCREEN_NETWORK;
2168 SCPY(e_callerinfo.extension, e_ext.number);
2169 if (e_ext.id_next_call_present >= 0)
2171 SCPY(e_callerinfo.id, e_ext.id_next_call);
2172 e_callerinfo.present = e_ext.id_next_call_present;
2173 e_callerinfo.ntype = e_ext.id_next_call_type;
2174 e_ext.id_next_call_present = -1;
2175 /* extension is written */
2176 write_extension(&e_ext, e_ext.number);
2179 SCPY(e_callerinfo.id, e_ext.callerid);
2180 e_callerinfo.present = e_ext.callerid_present;
2181 e_callerinfo.ntype = e_ext.callerid_type;
2183 e_callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
2185 e_connectedmode = 1; /* dtmf-hangup & disconnect prevention */
2188 /* check if caller id is NOT authenticated */
2189 if (!parse_callbackauth(e_ext.number, &e_callbackinfo))
2191 /* make call state to enter password */
2192 new_state(EPOINT_STATE_IN_OVERLAP);
2193 e_action = &action_password_write;
2194 e_match_timeout = 0;
2195 e_match_to_action = NULL;
2196 e_dialinginfo.id[0] = '\0';
2197 e_extdialing = strchr(e_dialinginfo.id, '\0');
2198 e_password_timeout = now+20;
2202 /* incoming call (callback) */
2203 e_ruleset = ruleset_main;
2205 e_rule = e_ruleset->rule_first;
2207 e_extdialing = e_dialinginfo.id;
2208 if (e_dialinginfo.id[0])
2210 set_tone(portlist, "dialing");
2214 set_tone(portlist, "dialpbx");
2217 } else /* testcall */
2219 set_tone(portlist, "hold");
2222 /* start recording if enabled, not when answering machine answers */
2223 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))
2225 /* check if we are a terminal */
2226 if (e_ext.number[0] == '\0')
2227 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
2230 port = find_port_id(portlist->port_id);
2232 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
2237 /* port MESSAGE_DISCONNECT MESSAGE_RELEASE */
2238 void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
2240 struct lcr_msg *message;
2242 unsigned int port_id = portlist->port_id;
2246 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2248 /* signal to call tool */
2249 admin_call_response(e_adminid, (message_type==MESSAGE_DISCONNECT)?ADMIN_CALL_DISCONNECT:ADMIN_CALL_RELEASE, "", param->disconnectinfo.cause, param->disconnectinfo.location, 0);
2251 //#warning does this work? only disconnect when incoming port hat not already disconnected yet?
2252 if (e_state==EPOINT_STATE_IN_DISCONNECT && message_type!=MESSAGE_RELEASE)// || e_state==EPOINT_STATE_OUT_DISCONNECT || e_state==EPOINT_STATE_IDLE)
2254 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are already disconnected.\n", ea_endpoint->ep_serial);
2259 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);
2260 collect_cause(&e_multipoint_cause, &e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location);
2261 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new multipoint cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location);
2263 /* check if we have more than one portlist relation and we just ignore the disconnect */
2264 if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist->next)
2266 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the disconnect was from a multipoint call. we just release that relation.\n", ea_endpoint->ep_serial);
2267 portlist = ea_endpoint->ep_portlist;
2270 if (portlist->port_id == port_id)
2272 portlist = portlist->next;
2275 FATAL("EPOINT(%d) no portlist related to the calling port.\n", ea_endpoint->ep_serial);
2276 if (message_type != MESSAGE_RELEASE)
2278 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2279 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2280 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2281 message_put(message);
2282 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2284 ea_endpoint->free_portlist(portlist);
2285 return; /* one relation removed */
2287 if (e_state == EPOINT_STATE_CONNECT)
2289 /* use cause from port after connect */
2290 cause = param->disconnectinfo.cause;
2291 location = param->disconnectinfo.location;
2294 /* use multipoint cause if no connect yet */
2295 if (e_multipoint_cause)
2297 cause = e_multipoint_cause;
2298 location = e_multipoint_location;
2301 cause = CAUSE_NOUSER;
2302 location = LOCATION_PRIVATE_LOCAL;
2306 e_cfnr_call = e_cfnr_release = 0;
2308 /* process hangup */
2309 process_hangup(e_join_cause, e_join_location);
2310 e_multipoint_cause = 0;
2311 e_multipoint_location = 0;
2313 if (message_type == MESSAGE_DISCONNECT)
2315 /* tone to disconnected end */
2316 SPRINT(buffer, "cause_%02x", cause);
2317 if (ea_endpoint->ep_portlist)
2318 set_tone(ea_endpoint->ep_portlist, buffer);
2320 new_state(EPOINT_STATE_IN_DISCONNECT);
2323 if (ea_endpoint->ep_join_id)
2325 int haspatterns = 0;
2326 /* check if pattern is available */
2327 if (ea_endpoint->ep_portlist)
2328 if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->early_b)
2329 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
2330 && message_type != MESSAGE_RELEASE) // if we release, we are done
2334 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has patterns.\n", ea_endpoint->ep_serial);
2335 /* indicate patterns */
2336 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2337 message_put(message);
2338 /* connect audio, if not already */
2339 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2340 message->param.audiopath = 1;
2341 message_put(message);
2342 /* send disconnect */
2343 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2344 memcpy(&message->param, param, sizeof(union parameter));
2345 message_put(message);
2346 /* disable encryption if disconnected */
2347 //PERROR("REMOVE ME: state =%d, %d\n", e_crypt_state, e_crypt);
2349 cryptman_message(CI_DISCONNECT_IND, NULL, 0);
2353 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
2356 if (message_type == MESSAGE_RELEASE)
2357 ea_endpoint->free_portlist(portlist);
2358 release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, callcause, portcause */
2359 return; /* must exit here */
2362 /* port MESSAGE_TIMEOUT */
2363 void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type, union parameter *param)
2367 trace_header("TIMEOUT", DIRECTION_IN);
2368 message_type = MESSAGE_DISCONNECT;
2369 switch (param->state)
2371 case PORT_STATE_OUT_SETUP:
2372 case PORT_STATE_OUT_OVERLAP:
2373 add_trace("state", NULL, "outgoing setup/dialing");
2375 /* no user responding */
2376 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2377 return; /* must exit here */
2379 case PORT_STATE_IN_SETUP:
2380 case PORT_STATE_IN_OVERLAP:
2381 add_trace("state", NULL, "incoming setup/dialing");
2382 param->disconnectinfo.cause = CAUSE_INVALID; /* number incomplete */
2383 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2386 case PORT_STATE_OUT_PROCEEDING:
2387 add_trace("state", NULL, "outgoing proceeding");
2389 param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
2390 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2391 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2392 return; /* must exit here */
2394 case PORT_STATE_IN_PROCEEDING:
2395 add_trace("state", NULL, "incoming proceeding");
2396 param->disconnectinfo.cause = CAUSE_NOUSER;
2397 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL; /* no user responding */
2400 case PORT_STATE_OUT_ALERTING:
2401 add_trace("state", NULL, "outgoing alerting");
2403 param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
2404 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2405 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2406 return; /* must exit here */
2408 case PORT_STATE_CONNECT:
2409 add_trace("state", NULL, "connect");
2411 param->disconnectinfo.cause = CAUSE_NORMAL; /* normal */
2412 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2413 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2414 return; /* must exit here */
2416 case PORT_STATE_IN_ALERTING:
2417 add_trace("state", NULL, "incoming alerting");
2418 param->disconnectinfo.cause = CAUSE_NOANSWER;
2419 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2422 case PORT_STATE_IN_DISCONNECT:
2423 case PORT_STATE_OUT_DISCONNECT:
2424 add_trace("state", NULL, "disconnect");
2426 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
2427 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2428 return; /* must exit here */
2431 param->disconnectinfo.cause = 31; /* normal unspecified */
2432 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2435 /* release call, disconnect isdn */
2437 new_state(EPOINT_STATE_OUT_DISCONNECT);
2438 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2439 SCPY(e_tone, cause);
2442 set_tone(portlist, cause);
2443 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2444 portlist = portlist->next;
2446 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
2449 /* port MESSAGE_NOTIFY */
2450 void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, union parameter *param)
2452 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2454 struct lcr_msg *message;
2455 const char *logtext = "";
2458 /* signal to call tool */
2459 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);
2460 if (param->notifyinfo.notify)
2462 e_rx_state = track_notify(e_rx_state, param->notifyinfo.notify);
2465 /* if we get notification from stack, local shows if we disabled/enabled audio stream */
2466 if (param->notifyinfo.local) switch(param->notifyinfo.notify)
2468 case INFO_NOTIFY_REMOTE_HOLD:
2469 case INFO_NOTIFY_USER_SUSPENDED:
2470 /* tell call about it */
2471 if (ea_endpoint->ep_join_id)
2473 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2474 message->param.audiopath = 0;
2475 message_put(message);
2479 case INFO_NOTIFY_REMOTE_RETRIEVAL:
2480 case INFO_NOTIFY_USER_RESUMED:
2481 /* set volume of rx and tx */
2482 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
2483 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
2486 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2487 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2488 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
2489 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
2490 message_put(message);
2492 /* set current tone */
2494 set_tone(portlist, e_tone);
2495 /* tell call about it */
2496 if (ea_endpoint->ep_join_id)
2498 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2499 message->param.audiopath = 1;
2500 message_put(message);
2505 /* get name of notify */
2506 switch(param->notifyinfo.notify)
2512 logtext = "USER_SUSPENDED";
2515 logtext = "BEARER_SERVICE_CHANGED";
2518 logtext = "USER_RESUMED";
2521 logtext = "CONFERENCE_ESTABLISHED";
2524 logtext = "CONFERENCE_DISCONNECTED";
2527 logtext = "OTHER_PARTY_ADDED";
2530 logtext = "ISOLATED";
2533 logtext = "REATTACHED";
2536 logtext = "OTHER_PARTY_ISOLATED";
2539 logtext = "OTHER_PARTY_REATTACHED";
2542 logtext = "OTHER_PARTY_SPLIT";
2545 logtext = "OTHER_PARTY_DISCONNECTED";
2548 logtext = "CONFERENCE_FLOATING";
2551 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
2554 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
2557 logtext = "CALL_IS_A_WAITING_CALL";
2560 logtext = "DIVERSION_ACTIVATED";
2563 logtext = "RESERVED_CT_1";
2566 logtext = "RESERVED_CT_2";
2569 logtext = "REVERSE_CHARGING";
2572 logtext = "REMOTE_HOLD";
2575 logtext = "REMOTE_RETRIEVAL";
2578 logtext = "CALL_IS_DIVERTING";
2581 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
2586 /* notify call if available */
2587 if (ea_endpoint->ep_join_id)
2589 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOTIFY);
2590 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
2591 message_put(message);
2596 /* port MESSAGE_FACILITY */
2597 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
2599 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2601 struct lcr_msg *message;
2603 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_FACILITY);
2604 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2605 message_put(message);
2608 /* port MESSAGE_SUSPEND */
2609 /* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
2610 void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
2612 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2614 /* epoint is now parked */
2615 ea_endpoint->ep_park = 1;
2616 memcpy(ea_endpoint->ep_park_callid, param->parkinfo.callid, sizeof(ea_endpoint->ep_park_callid));
2617 ea_endpoint->ep_park_len = (param->parkinfo.len>8)?8:param->parkinfo.len;
2619 /* remove port relation */
2620 ea_endpoint->free_portlist(portlist);
2623 /* port MESSAGE_RESUME */
2624 /* NOTE: before resume, the active-notification must be done in order to set call mixer */
2625 void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
2627 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2629 /* epoint is now resumed */
2630 ea_endpoint->ep_park = 0;
2635 /* port sends message to the endpoint
2637 void EndpointAppPBX::ea_message_port(unsigned int port_id, int message_type, union parameter *param)
2639 struct port_list *portlist;
2641 portlist = ea_endpoint->ep_portlist;
2644 if (port_id == portlist->port_id)
2646 portlist = portlist->next;
2650 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);
2654 // PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
2655 switch(message_type)
2657 case MESSAGE_DATA: /* data from port */
2658 /* check if there is a call */
2659 if (!ea_endpoint->ep_join_id)
2661 /* continue if only one portlist */
2662 if (ea_endpoint->ep_portlist->next != NULL)
2664 /* forward message */
2665 message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2668 case MESSAGE_TONE_EOF: /* tone is end of file */
2669 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
2672 if (e_action->index == ACTION_VBOX_PLAY)
2676 if (e_action->index == ACTION_EFI)
2683 case MESSAGE_TONE_COUNTER: /* counter info received */
2684 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);
2686 if (e_action->index == ACTION_VBOX_PLAY)
2688 e_vbox_counter = param->counter.current;
2689 if (param->counter.max >= 0)
2690 e_vbox_counter_max = param->counter.max;
2694 /* PORT sends SETUP message */
2696 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);
2697 if (e_state!=EPOINT_STATE_IDLE)
2699 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
2702 port_setup(portlist, message_type, param);
2705 /* PORT sends INFORMATION message */
2706 case MESSAGE_INFORMATION: /* additional digits received */
2707 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);
2708 port_information(portlist, message_type, param);
2711 /* PORT sends FACILITY message */
2712 case MESSAGE_FACILITY:
2713 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2714 port_facility(portlist, message_type, param);
2717 /* PORT sends DTMF message */
2718 case MESSAGE_DTMF: /* dtmf digits received */
2719 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);
2720 port_dtmf(portlist, message_type, param);
2723 /* PORT sends CRYPT message */
2724 case MESSAGE_CRYPT: /* crypt response received */
2725 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) crypt response=%d\n", ea_endpoint->ep_serial, param->crypt.type);
2726 port_crypt(portlist, message_type, param);
2729 /* PORT sends MORE message */
2730 case MESSAGE_OVERLAP:
2731 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);
2732 if (e_state != EPOINT_STATE_OUT_SETUP)
2734 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);
2737 port_overlap(portlist, message_type, param);
2740 /* PORT sends PROCEEDING message */
2741 case MESSAGE_PROCEEDING: /* port is proceeding */
2742 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);
2743 if (e_state!=EPOINT_STATE_OUT_SETUP
2744 && e_state!=EPOINT_STATE_OUT_OVERLAP)
2746 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);
2749 port_proceeding(portlist, message_type, param);
2752 /* PORT sends ALERTING message */
2753 case MESSAGE_ALERTING:
2754 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);
2755 if (e_state!=EPOINT_STATE_OUT_SETUP
2756 && e_state!=EPOINT_STATE_OUT_OVERLAP
2757 && e_state!=EPOINT_STATE_OUT_PROCEEDING)
2759 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);
2762 port_alerting(portlist, message_type, param);
2765 /* PORT sends CONNECT message */
2766 case MESSAGE_CONNECT:
2767 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);
2768 if (e_state!=EPOINT_STATE_OUT_SETUP
2769 && e_state!=EPOINT_STATE_OUT_OVERLAP
2770 && e_state!=EPOINT_STATE_OUT_PROCEEDING
2771 && e_state!=EPOINT_STATE_OUT_ALERTING)
2773 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
2776 port_connect(portlist, message_type, param);
2779 /* PORT sends DISCONNECT message */
2780 case MESSAGE_DISCONNECT: /* port is disconnected */
2781 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);
2782 port_disconnect_release(portlist, message_type, param);
2785 /* PORT sends a RELEASE message */
2786 case MESSAGE_RELEASE: /* port releases */
2787 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);
2788 /* portlist is release at port_disconnect_release, thanx Paul */
2789 port_disconnect_release(portlist, message_type, param);
2792 /* PORT sends a TIMEOUT message */
2793 case MESSAGE_TIMEOUT:
2794 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);
2795 port_timeout(portlist, message_type, param);
2796 break; /* release */
2798 /* PORT sends a NOTIFY message */
2799 case MESSAGE_NOTIFY:
2800 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);
2801 port_notify(portlist, message_type, param);
2804 /* PORT sends a SUSPEND message */
2805 case MESSAGE_SUSPEND:
2806 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);
2807 port_suspend(portlist, message_type, param);
2808 break; /* suspend */
2810 /* PORT sends a RESUME message */
2811 case MESSAGE_RESUME:
2812 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);
2813 port_resume(portlist, message_type, param);
2817 kann nach dem test gelöscht werden, da eine direkte funktion im join und im mISDN zum austausch der message existiert
2818 /* port assigns bchannel */
2819 case MESSAGE_BCHANNEL: /* bchannel assignment messafe */
2820 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);
2821 /* only one port is expected to be connected to bchannel */
2822 message = message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2823 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_IN);
2829 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);
2832 /* Note: this endpoint may be destroyed, so we MUST return */
2836 /* messages from join
2838 /* join MESSAGE_CRYPT */
2839 void EndpointAppPBX::join_crypt(struct port_list *portlist, int message_type, union parameter *param)
2841 switch(param->crypt.type)
2843 /* message from remote port to "crypt manager" */
2844 case CU_ACTK_REQ: /* activate key-exchange */
2845 case CU_ACTS_REQ: /* activate shared key */
2846 case CU_DACT_REQ: /* deactivate */
2847 case CU_INFO_REQ: /* request last info message */
2848 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2851 /* message from "crypt manager" to user */
2852 case CU_ACTK_CONF: /* key-echange done */
2853 case CU_ACTS_CONF: /* shared key done */
2854 case CU_DACT_CONF: /* deactivated */
2855 case CU_DACT_IND: /* deactivated */
2856 case CU_ERROR_IND: /* receive error message */
2857 case CU_INFO_IND: /* receive info message */
2858 case CU_INFO_CONF: /* receive info message */
2859 encrypt_result(param->crypt.type, (char *)param->crypt.data);
2863 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);
2867 /* join MESSAGE_INFORMATION */
2868 void EndpointAppPBX::join_information(struct port_list *portlist, int message_type, union parameter *param)
2870 struct lcr_msg *message;
2876 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2877 memcpy(&message->param.information, ¶m->information, sizeof(struct dialing_info));
2878 message_put(message);
2879 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2880 portlist = portlist->next;
2884 /* join MESSAGE_FACILITY */
2885 void EndpointAppPBX::join_facility(struct port_list *portlist, int message_type, union parameter *param)
2887 struct lcr_msg *message;
2889 if (!e_ext.facility && e_ext.number[0])
2896 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_FACILITY);
2897 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2898 message_put(message);
2899 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2900 portlist = portlist->next;
2904 /* join MESSAGE_MORE */
2905 void EndpointAppPBX::join_overlap(struct port_list *portlist, int message_type, union parameter *param)
2907 struct lcr_msg *message;
2909 new_state(EPOINT_STATE_IN_OVERLAP);
2912 if (e_join_pattern && e_ext.own_setup)
2914 /* disconnect audio */
2915 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2916 message->param.audiopath = 0;
2917 message_put(message);
2919 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
2921 if (e_dialinginfo.id[0])
2922 set_tone(portlist, "dialing");
2924 set_tone(portlist, "dialtone");
2927 if (e_dialinginfo.id[0])
2929 set_tone(portlist, "dialing");
2932 if (e_ext.number[0])
2933 set_tone(portlist, "dialpbx");
2935 set_tone(portlist, "dialtone");
2939 /* join MESSAGE_PROCEEDING */
2940 void EndpointAppPBX::join_proceeding(struct port_list *portlist, int message_type, union parameter *param)
2942 struct lcr_msg *message;
2944 new_state(EPOINT_STATE_IN_PROCEEDING);
2946 /* own proceeding tone */
2949 /* connect / disconnect audio */
2950 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2951 if (e_ext.own_proceeding)
2952 message->param.audiopath = 0;
2954 message->param.audiopath = 1;
2955 message_put(message);
2957 // UCPY(e_join_tone, "proceeding");
2960 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
2961 message_put(message);
2962 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2964 set_tone(portlist, "proceeding");
2967 /* join MESSAGE_ALERTING */
2968 void EndpointAppPBX::join_alerting(struct port_list *portlist, int message_type, union parameter *param)
2970 struct lcr_msg *message;
2972 new_state(EPOINT_STATE_IN_ALERTING);
2974 /* own alerting tone */
2977 /* connect / disconnect audio */
2978 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2979 if (e_ext.own_alerting)
2980 message->param.audiopath = 0;
2982 message->param.audiopath = 1;
2983 message_put(message);
2987 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
2988 message_put(message);
2989 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2991 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
2993 set_tone(portlist, "ringing");
2996 if (e_ext.number[0])
2997 set_tone(portlist, "ringpbx");
2999 set_tone(portlist, "ringing");
3002 /* join MESSAGE_CONNECT */
3003 void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type, union parameter *param)
3005 struct lcr_msg *message;
3007 new_state(EPOINT_STATE_CONNECT);
3008 // UCPY(e_join_tone, "");
3010 if (e_ext.number[0])
3011 e_dtmf = 1; /* allow dtmf */
3014 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_callerinfo));
3017 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3018 memcpy(&message->param, param, sizeof(union parameter));
3020 /* screen clip if prefix is required */
3021 if (e_ext.number[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0])
3023 SCPY(message->param.connectinfo.id, e_ext.clip_prefix);
3024 SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype, options.national, options.international));
3025 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
3028 /* use internal caller id */
3029 if (e_ext.number[0] && e_connectinfo.extension[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
3031 SCPY(message->param.connectinfo.id, e_connectinfo.extension);
3032 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
3035 /* handle restricted caller ids */
3036 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);
3037 /* display callerid if desired for extension */
3038 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));
3040 /* use conp, if enabld */
3041 // if (!e_ext.centrex)
3042 // message->param.connectinfo.name[0] = '\0';
3045 message_put(message);
3046 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3048 set_tone(portlist, NULL);
3050 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3051 message->param.audiopath = 1;
3052 message_put(message);
3056 /* join MESSAGE_DISCONNECT MESSAGE_RELEASE */
3057 void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *param)
3060 struct lcr_msg *message;
3061 struct port_list *portlist = NULL;
3064 /* be sure that we are active */
3066 e_tx_state = NOTIFY_STATE_ACTIVE;
3068 /* we are powerdialing, if e_powerdialing is set and limit is not exceeded if given */
3069 if (e_powerdialing && ((e_powercount+1)<e_powerlimit || e_powerlimit<1))
3071 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
3073 /* set time for power dialing */
3074 e_powerdialing = now_d + e_powerdelay; /* set redial in the future */
3077 /* set redial tone */
3078 if (ea_endpoint->ep_portlist)
3082 set_tone(ea_endpoint->ep_portlist, "redial");
3083 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);
3084 /* send proceeding when powerdialing and still setup (avoid dialing timeout) */
3085 if (e_state==EPOINT_STATE_IN_OVERLAP)
3087 new_state(EPOINT_STATE_IN_PROCEEDING);
3088 if (ea_endpoint->ep_portlist)
3090 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3091 message_put(message);
3092 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3094 /* caused the error, that the first knock sound was not there */
3095 /* set_tone(portlist, "proceeding"); */
3097 /* send display of powerdialing */
3098 if (e_ext.display_dialing)
3100 portlist = ea_endpoint->ep_portlist;
3103 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3105 SPRINT(message->param.notifyinfo.display, "Retry %d of %d", e_powercount, e_powerlimit);
3107 SPRINT(message->param.notifyinfo.display, "Retry %d", e_powercount);
3108 message_put(message);
3109 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3110 portlist = portlist->next;
3119 if ((e_state!=EPOINT_STATE_CONNECT
3120 && e_state!=EPOINT_STATE_OUT_DISCONNECT
3121 && e_state!=EPOINT_STATE_IN_OVERLAP
3122 && e_state!=EPOINT_STATE_IN_PROCEEDING
3123 && e_state!=EPOINT_STATE_IN_ALERTING)
3124 || !ea_endpoint->ep_portlist) /* or no port */
3126 process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
3127 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause); /* RELEASE_TYPE, join, port */
3128 return; /* must exit here */
3133 e_join_cause = param->disconnectinfo.cause;
3134 e_join_location = param->disconnectinfo.location;
3137 /* on release we need the audio again! */
3138 if (message_type == MESSAGE_RELEASE)
3141 ea_endpoint->ep_join_id = 0;
3143 /* disconnect and select tone */
3144 new_state(EPOINT_STATE_OUT_DISCONNECT);
3145 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
3146 /* if own_cause, we must release the join */
3147 if (e_ext.own_cause /* own cause */
3148 || !e_join_pattern) /* no patterns */
3150 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);
3151 if (message_type != MESSAGE_RELEASE)
3152 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
3154 } else /* else we enable audio */
3156 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3157 message->param.audiopath = 1;
3158 message_put(message);
3160 /* send disconnect message */
3161 SCPY(e_tone, cause);
3162 portlist = ea_endpoint->ep_portlist;
3165 set_tone(portlist, cause);
3166 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
3167 portlist = portlist->next;
3171 /* join MESSAGE_SETUP */
3172 void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, union parameter *param)
3174 struct lcr_msg *message;
3175 // struct interface *interface;
3177 /* if we already in setup state, we just update the dialing with new digits */
3178 if (e_state == EPOINT_STATE_OUT_SETUP
3179 || e_state == EPOINT_STATE_OUT_OVERLAP)
3181 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we are in setup state, so we do overlap dialing.\n", ea_endpoint->ep_serial);
3182 /* if digits changed, what we have already dialed */
3183 if (!!strncmp(e_dialinginfo.id,param->setup.dialinginfo.id,strlen(e_dialinginfo.id)))
3185 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);
3186 /* release all ports */
3187 while((portlist = ea_endpoint->ep_portlist))
3189 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
3190 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
3191 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3192 message_put(message);
3193 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3194 ea_endpoint->free_portlist(portlist);
3197 /* disconnect audio */
3198 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3199 message->param.audiopath = 0;
3200 message_put(message);
3202 /* get dialing info */
3203 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3204 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3205 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3206 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3207 new_state(EPOINT_STATE_OUT_OVERLAP);
3210 e_redial = now_d + 1; /* set redial one second in the future */
3213 /* if we have a pending redial, so we just adjust the dialing number */
3216 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);
3217 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3220 if (!ea_endpoint->ep_portlist)
3222 PERROR("ERROR: overlap dialing to a NULL port relation\n");
3224 if (ea_endpoint->ep_portlist->next)
3226 PERROR("ERROR: overlap dialing to a port_list port relation\n");
3228 if (e_state == EPOINT_STATE_OUT_SETUP)
3231 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);
3232 SCAT(e_dialing_queue, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3236 /* get what we have not dialed yet */
3237 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));
3238 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
3239 SCPY(message->param.information.id, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3240 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
3241 message_put(message);
3242 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3244 /* always store what we have dialed or queued */
3245 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3249 if (e_state != EPOINT_STATE_IDLE)
3251 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
3254 /* if an internal extension is dialed, copy that number */
3255 if (param->setup.dialinginfo.itype==INFO_ITYPE_ISDN_EXTENSION || param->setup.dialinginfo.itype==INFO_ITYPE_VBOX)
3256 SCPY(e_ext.number, param->setup.dialinginfo.id);
3257 /* if an internal extension is dialed, get extension's info about caller */
3258 if (e_ext.number[0])
3260 if (!read_extension(&e_ext, e_ext.number))
3262 e_ext.number[0] = '\0';
3263 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the called terminal='%s' is not found in directory tree!\n", ea_endpoint->ep_serial, e_ext.number);
3267 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3268 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3269 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3270 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3272 /* process (voice over) data calls */
3273 if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO)
3275 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) handling data call as audio call: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
3276 memset(&e_capainfo, 0, sizeof(e_capainfo));
3277 e_capainfo.bearer_capa = INFO_BC_AUDIO;
3278 e_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
3279 e_capainfo.bearer_info1 = (options.law=='u')?INFO_INFO1_ULAW:INFO_INFO1_ALAW;
3282 new_state(EPOINT_STATE_OUT_SETUP);
3283 /* call special setup routine */
3287 /* join MESSAGE_mISDNSIGNAL */
3288 void EndpointAppPBX::join_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param)
3290 struct lcr_msg *message;
3294 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
3295 memcpy(&message->param, param, sizeof(union parameter));
3296 message_put(message);
3297 portlist = portlist->next;
3301 /* join MESSAGE_NOTIFY */
3302 void EndpointAppPBX::join_notify(struct port_list *portlist, int message_type, union parameter *param)
3304 struct lcr_msg *message;
3307 if (param->notifyinfo.notify)
3309 new_state = track_notify(e_tx_state, param->notifyinfo.notify);
3310 // /* if notification was generated locally, we turn hold music on/off */
3311 // if (param->notifyinfo.local)
3312 // 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)
3317 if (new_state!=NOTIFY_STATE_HOLD && new_state!=NOTIFY_STATE_SUSPEND)
3319 if (!strcmp(e_tone, "hold")) // don't interrupt other tones
3323 set_tone(portlist, "");
3324 portlist = portlist->next;
3327 portlist = ea_endpoint->ep_portlist;
3332 if (new_state==NOTIFY_STATE_HOLD || new_state==NOTIFY_STATE_SUSPEND)
3336 set_tone(portlist, "hold");
3337 portlist = portlist->next;
3339 portlist = ea_endpoint->ep_portlist;
3344 /* save new state */
3345 e_tx_state = new_state;
3348 /* notify port(s) about it */
3351 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3352 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
3353 /* handle restricted caller ids */
3354 apply_callerid_restriction(&e_ext, message->param.notifyinfo.id, &message->param.notifyinfo.ntype, &message->param.notifyinfo.present, 0, message->param.notifyinfo.extension, NULL);
3355 /* display callerid if desired for extension */
3356 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));
3357 message_put(message);
3358 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3359 portlist = portlist->next;
3363 /* JOIN sends messages to the endpoint
3365 void EndpointAppPBX::ea_message_join(unsigned int join_id, int message_type, union parameter *param)
3367 struct port_list *portlist;
3368 struct lcr_msg *message;
3372 PERROR("EPOINT(%d) error: JOIN == NULL.\n", ea_endpoint->ep_serial);
3376 portlist = ea_endpoint->ep_portlist;
3378 /* send MESSAGE_DATA to port */
3379 if (message_type == MESSAGE_DATA)
3381 if (join_id == ea_endpoint->ep_join_id) // still linked with JOIN
3383 /* skip if no port relation */
3386 /* skip if more than one port relation */
3389 /* forward audio data to port */
3390 message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3395 // 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);
3396 switch(message_type)
3398 /* JOIN SENDS TONE message */
3400 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);
3401 set_tone(portlist, param->tone.name);
3404 /* JOIN SENDS CRYPT message */
3406 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);
3407 join_crypt(portlist, message_type, param);
3410 /* JOIN sends INFORMATION message */
3411 case MESSAGE_INFORMATION:
3412 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);
3413 join_information(portlist, message_type, param);
3416 /* JOIN sends FACILITY message */
3417 case MESSAGE_FACILITY:
3418 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);
3419 join_facility(portlist, message_type, param);
3422 /* JOIN sends OVERLAP message */
3423 case MESSAGE_OVERLAP:
3424 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);
3425 if (e_state!=EPOINT_STATE_IN_SETUP
3426 && e_state!=EPOINT_STATE_IN_OVERLAP)
3428 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3431 join_overlap(portlist, message_type, param);
3434 /* JOIN sends PROCEEDING message */
3435 case MESSAGE_PROCEEDING:
3436 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);
3437 if(e_state!=EPOINT_STATE_IN_OVERLAP)
3439 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3442 join_proceeding(portlist, message_type, param);
3445 /* JOIN sends ALERTING message */
3446 case MESSAGE_ALERTING:
3447 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);
3448 if (e_state!=EPOINT_STATE_IN_OVERLAP
3449 && e_state!=EPOINT_STATE_IN_PROCEEDING)
3451 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state.\n", ea_endpoint->ep_serial);
3454 join_alerting(portlist, message_type, param);
3457 /* JOIN sends CONNECT message */
3458 case MESSAGE_CONNECT:
3459 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);
3460 if (e_state!=EPOINT_STATE_IN_OVERLAP
3461 && e_state!=EPOINT_STATE_IN_PROCEEDING
3462 && e_state!=EPOINT_STATE_IN_ALERTING)
3464 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
3467 join_connect(portlist, message_type, param);
3470 /* JOIN sends DISCONNECT/RELEASE message */
3471 case MESSAGE_DISCONNECT: /* JOIN disconnect */
3472 case MESSAGE_RELEASE: /* JOIN releases */
3473 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);
3474 join_disconnect_release(message_type, param);
3477 /* JOIN sends SETUP message */
3479 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);
3480 join_setup(portlist, message_type, param);
3483 /* JOIN sends special mISDNSIGNAL message */
3484 case MESSAGE_mISDNSIGNAL: /* isdn message to port */
3485 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);
3486 join_mISDNsignal(portlist, message_type, param);
3490 kann nach dem test gelöscht werden, da eine direkte funktion im join und im mISDN zum austausch der message existiert
3491 /* JOIN requests bchannel */
3492 case MESSAGE_BCHANNEL: /* indicates the need of own bchannel access */
3493 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);
3494 /* only one port is expected to be connected to bchannel */
3501 set_tone(portlist, NULL);
3502 message = message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3503 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3507 /* JOIN has pattern available */
3508 case MESSAGE_PATTERN: /* indicating pattern available */
3509 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);
3510 if (!e_join_pattern)
3512 PDEBUG(DEBUG_EPOINT, "-> pattern becomes available\n");
3517 set_tone(portlist, NULL);
3518 portlist = portlist->next;
3520 /* connect our audio tx and rx (blueboxing should be possibe before connect :)*/
3521 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3522 message->param.audiopath = 1;
3523 message_put(message);
3527 /* JOIN has no pattern available */
3528 case MESSAGE_NOPATTERN: /* indicating no pattern available */
3529 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);
3532 PDEBUG(DEBUG_EPOINT, "-> pattern becomes unavailable\n");
3534 /* disconnect our audio tx and rx */
3535 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3536 message->param.audiopath = 0;
3537 message_put(message);
3542 /* JOIN (dunno at the moment) */
3543 case MESSAGE_REMOTE_AUDIO:
3544 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);
3545 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3546 message->param.audiopath = param->channel;
3547 message_put(message);
3551 /* JOIN sends a notify message */
3552 case MESSAGE_NOTIFY:
3553 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);
3554 join_notify(portlist, message_type, param);
3557 /* JOIN wants keypad / dtml */
3558 case MESSAGE_ENABLEKEYPAD:
3559 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);
3562 trace_header("ENABLE KEYPAD", DIRECTION_NONE);
3567 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);
3572 /* pick_join will connect the first incoming call found. the endpoint
3573 * will receivce a MESSAGE_CONNECT.
3575 int match_list(char *list, char *item)
3577 char *end, *next = NULL;
3579 /* no list make matching */
3585 /* eliminate white spaces */
3586 while (*list <= ' ')
3593 /* if end of list is reached, we return */
3594 if (list[0] == '\0')
3596 /* if we have more than one entry (left) */
3597 if ((end = strchr(list, ',')))
3600 next = end = strchr(list, '\0');
3601 while (*(end-1) <= ' ')
3603 /* if string part matches item */
3604 if (!strncmp(list, item, end-list))
3610 void EndpointAppPBX::pick_join(char *extensions)
3612 struct lcr_msg *message;
3613 struct port_list *portlist;
3615 class EndpointAppPBX *eapp, *found;
3617 class JoinPBX *joinpbx;
3618 struct join_relation *relation;
3621 /* find an endpoint that is ringing internally or vbox with higher priority */
3624 eapp = apppbx_first;
3627 if (eapp!=this && ea_endpoint->ep_portlist)
3629 portlist = eapp->ea_endpoint->ep_portlist;
3632 if ((port = find_port_id(portlist->port_id)))
3634 if (port->p_type == PORT_TYPE_VBOX_OUT)
3636 if (match_list(extensions, eapp->e_ext.number))
3643 if ((port->p_type==PORT_TYPE_DSS1_NT_OUT || port->p_type==PORT_TYPE_DSS1_TE_OUT || port->p_type==PORT_TYPE_GSM_OUT)
3644 && port->p_state==PORT_STATE_OUT_ALERTING)
3645 if (match_list(extensions, eapp->e_ext.number))
3650 portlist = portlist->next;
3658 /* if no endpoint found */
3661 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);
3663 set_tone(ea_endpoint->ep_portlist, "cause_10");
3664 message_disconnect_port(ea_endpoint->ep_portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
3665 new_state(EPOINT_STATE_OUT_DISCONNECT);
3670 if (ea_endpoint->ep_join_id)
3672 PERROR("EPOINT(%d) we already have a join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3675 if (!eapp->ea_endpoint->ep_join_id)
3677 PERROR("EPOINT(%d) ringing endpoint has no join.\n", ea_endpoint->ep_serial);
3680 join = find_join_id(eapp->ea_endpoint->ep_join_id);
3683 PERROR("EPOINT(%d) ringing endpoint's join not found.\n", ea_endpoint->ep_serial);
3686 if (join->j_type != JOIN_TYPE_PBX)
3688 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ringing endpoint's join is not a PBX join, so we must reject.\n", ea_endpoint->ep_serial);
3691 joinpbx = (class JoinPBX *)join;
3692 relation = joinpbx->j_relation;
3695 PERROR("EPOINT(%d) ringing endpoint's join has no relation. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3698 while (relation->epoint_id != eapp->ea_endpoint->ep_serial)
3700 relation = relation->next;
3703 PERROR("EPOINT(%d) ringing endpoint's join has no relation to that join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3708 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found ringing endpoint: %d.\n", ea_endpoint->ep_serial, eapp->ea_endpoint->ep_serial);
3710 if (options.deb & DEBUG_EPOINT)
3712 class Join *debug_c = join_first;
3713 class Endpoint *debug_e = epoint_first;
3714 class Port *debug_p = port_first;
3716 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(before)");
3718 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3721 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3722 debug_c = debug_c->next;
3724 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3727 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3728 debug_e = debug_e->next;
3730 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3733 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld (active)\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3734 debug_p = debug_p->next;
3739 ea_endpoint->ep_join_id = eapp->ea_endpoint->ep_join_id; /* we get the join */
3740 relation->epoint_id = ea_endpoint->ep_serial; /* the join gets us */
3741 eapp->ea_endpoint->ep_join_id = 0; /* the ringing endpoint will get disconnected */
3743 /* connnecting our endpoint */
3744 new_state(EPOINT_STATE_CONNECT);
3745 if (e_ext.number[0])
3747 set_tone(ea_endpoint->ep_portlist, NULL);
3749 /* now we send a release to the ringing endpoint */
3750 message = message_create(ea_endpoint->ep_join_id, eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3751 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
3752 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3753 message_put(message);
3755 /* we send a connect to the join with our caller id */
3756 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CONNECT);
3757 SCPY(message->param.connectinfo.id, e_callerinfo.id);
3758 message->param.connectinfo.present = e_callerinfo.present;
3759 message->param.connectinfo.screen = e_callerinfo.screen;
3760 message->param.connectinfo.itype = e_callerinfo.itype;
3761 message->param.connectinfo.ntype = e_callerinfo.ntype;
3762 message_put(message);
3764 /* we send a connect to our port with the remote callerid */
3765 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3766 SCPY(message->param.connectinfo.id, eapp->e_callerinfo.id);
3767 message->param.connectinfo.present = eapp->e_callerinfo.present;
3768 message->param.connectinfo.screen = eapp->e_callerinfo.screen;
3769 message->param.connectinfo.itype = eapp->e_callerinfo.itype;
3770 message->param.connectinfo.ntype = eapp->e_callerinfo.ntype;
3771 /* handle restricted caller ids */
3772 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);
3773 /* display callerid if desired for extension */
3774 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));
3775 message_put(message);
3777 /* we send a connect to the audio path (not for vbox) */
3778 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3779 message->param.audiopath = 1;
3780 message_put(message);
3782 /* beeing paranoid, we make call update */
3783 joinpbx->j_updatebridge = 1;
3785 if (options.deb & DEBUG_EPOINT)
3787 class Join *debug_c = join_first;
3788 class Endpoint *debug_e = epoint_first;
3789 class Port *debug_p = port_first;
3791 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(after)");
3793 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3796 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3797 debug_c = debug_c->next;
3799 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3802 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3803 debug_e = debug_e->next;
3805 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3808 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3809 debug_p = debug_p->next;
3815 /* join calls (look for a join that is on hold (same isdn interface/terminal))
3817 void EndpointAppPBX::join_join(void)
3819 struct lcr_msg *message;
3820 struct join_relation *our_relation, *other_relation;
3821 struct join_relation **our_relation_pointer, **other_relation_pointer;
3822 class Join *our_join, *other_join;
3823 class JoinPBX *our_joinpbx, *other_joinpbx;
3824 class EndpointAppPBX *other_eapp; class Endpoint *temp_epoint;
3825 class Port *our_port, *other_port;
3826 class Pdss1 *our_pdss1, *other_pdss1;
3828 /* are we a candidate to join a join */
3829 our_join = find_join_id(ea_endpoint->ep_join_id);
3832 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3835 if (our_join->j_type != JOIN_TYPE_PBX)
3837 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: join is not a pbx join.\n", ea_endpoint->ep_serial);
3840 our_joinpbx = (class JoinPBX *)our_join;
3841 if (!ea_endpoint->ep_portlist)
3843 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
3846 if (!e_ext.number[0])
3848 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
3851 our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
3854 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
3857 if ((our_port->p_type&PORT_CLASS_mISDN_MASK) != PORT_CLASS_mISDN_DSS1)
3859 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not isdn.\n", ea_endpoint->ep_serial);
3862 our_pdss1 = (class Pdss1 *)our_port;
3864 /* find an endpoint that is on hold and has the same mISDNport that we are on */
3865 other_eapp = apppbx_first;
3868 if (other_eapp == this)
3870 other_eapp = other_eapp->next;
3873 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);
3874 if (other_eapp->e_ext.number[0] /* has terminal */
3875 && other_eapp->ea_endpoint->ep_portlist /* has port */
3876 && other_eapp->ea_endpoint->ep_join_id) /* has join */
3878 other_port = find_port_id(other_eapp->ea_endpoint->ep_portlist->port_id);
3879 if (other_port) /* port still exists */
3881 if (other_port->p_type==PORT_TYPE_DSS1_NT_OUT
3882 || other_port->p_type==PORT_TYPE_DSS1_NT_IN) /* port is isdn nt-mode */
3884 other_pdss1 = (class Pdss1 *)other_port;
3885 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);
3886 if (other_pdss1->p_m_hold /* port is on hold */
3887 && other_pdss1->p_m_mISDNport == our_pdss1->p_m_mISDNport /* same isdn interface */
3888 && other_pdss1->p_m_d_ces == our_pdss1->p_m_d_ces) /* same tei+sapi */
3892 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of other type!\n", ea_endpoint->ep_serial);
3896 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port doesn't exist enymore.\n", ea_endpoint->ep_serial);
3899 other_eapp = other_eapp->next;
3903 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn interface with port on hold.\n", ea_endpoint->ep_serial);
3906 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port on hold found.\n", ea_endpoint->ep_serial);
3908 /* if we have the same join */
3909 if (other_eapp->ea_endpoint->ep_join_id == ea_endpoint->ep_join_id)
3911 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we an the other have the same join.\n", ea_endpoint->ep_serial);
3914 other_join = find_join_id(other_eapp->ea_endpoint->ep_join_id);
3917 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3920 if (other_join->j_type != JOIN_TYPE_PBX)
3922 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join is not a pbx join.\n", ea_endpoint->ep_serial);
3925 other_joinpbx = (class JoinPBX *)other_join;
3926 if (our_joinpbx->j_partyline && other_joinpbx->j_partyline)
3928 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both joins are partylines.\n", ea_endpoint->ep_serial);
3932 /* remove relation to endpoint for join on hold */
3933 other_relation = other_joinpbx->j_relation;
3934 other_relation_pointer = &other_joinpbx->j_relation;
3935 while(other_relation)
3937 if (other_relation->epoint_id == other_eapp->ea_endpoint->ep_serial)
3939 /* detach other endpoint on hold */
3940 *other_relation_pointer = other_relation->next;
3941 FREE(other_relation, sizeof(struct join_relation));
3943 other_relation = *other_relation_pointer;
3944 other_eapp->ea_endpoint->ep_join_id = 0;
3948 /* change join/hold pointer of endpoint to the new join */
3949 temp_epoint = find_epoint_id(other_relation->epoint_id);
3952 if (temp_epoint->ep_join_id == other_join->j_serial)
3953 temp_epoint->ep_join_id = our_join->j_serial;
3956 other_relation_pointer = &other_relation->next;
3957 other_relation = other_relation->next;
3959 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint on hold removed, other enpoints on join relinked (to our join).\n", ea_endpoint->ep_serial);
3961 /* join call relations */
3962 our_relation = our_joinpbx->j_relation;
3963 our_relation_pointer = &our_joinpbx->j_relation;
3966 our_relation_pointer = &our_relation->next;
3967 our_relation = our_relation->next;
3969 *our_relation_pointer = other_joinpbx->j_relation;
3970 other_joinpbx->j_relation = NULL;
3971 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) relations joined.\n", ea_endpoint->ep_serial);
3973 /* release endpoint on hold */
3974 message = message_create(other_joinpbx->j_serial, other_eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3975 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */
3976 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3977 message_put(message);
3979 /* if we are not a partyline, we get partyline state from other join */
3980 our_joinpbx->j_partyline += other_joinpbx->j_partyline;
3982 /* remove empty join */
3984 PDEBUG(DEBUG_EPOINT, "EPOINT(%d)d-join completely removed!\n");
3986 /* mixer must update */
3987 our_joinpbx->j_updatebridge = 1; /* update mixer flag */
3989 /* we send a retrieve to that endpoint */
3990 // mixer will update the hold-state of the join and send it to the endpoints is changes
3994 /* check if we have an external call
3995 * this is used to check for encryption ability
3997 int EndpointAppPBX::check_external(const char **errstr, class Port **port)
3999 struct join_relation *relation;
4001 class JoinPBX *joinpbx;
4002 class Endpoint *epoint;
4004 /* some paranoia check */
4005 if (!ea_endpoint->ep_portlist)
4007 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we have no port.\n", ea_endpoint->ep_serial);
4008 *errstr = "No Call";
4011 if (!e_ext.number[0])
4013 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we are not internal extension.\n", ea_endpoint->ep_serial);
4014 *errstr = "No Call";
4018 /* check if we have a join with 2 parties */
4019 join = find_join_id(ea_endpoint->ep_join_id);
4022 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have currently no join.\n", ea_endpoint->ep_serial);
4023 *errstr = "No Call";
4026 if (join->j_type != JOIN_TYPE_PBX)
4028 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join is not a pbx join.\n", ea_endpoint->ep_serial);
4029 *errstr = "No PBX Call";
4032 joinpbx = (class JoinPBX *)join;
4033 relation = joinpbx->j_relation;
4036 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no relation.\n", ea_endpoint->ep_serial);
4037 *errstr = "No Call";
4040 if (!relation->next)
4042 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd relation.\n", ea_endpoint->ep_serial);
4043 *errstr = "No Call";
4046 if (relation->next->next)
4048 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has more than two relations.\n", ea_endpoint->ep_serial);
4049 *errstr = "Err: Conference";
4052 if (relation->epoint_id == ea_endpoint->ep_serial)
4054 relation = relation->next;
4055 if (relation->epoint_id == ea_endpoint->ep_serial)
4057 PERROR("EPOINT(%d) SOFTWARE ERROR: both join relations are related to our endpoint.\n", ea_endpoint->ep_serial);
4058 *errstr = "Software Error";
4063 /* check remote port for external call */
4064 epoint = find_epoint_id(relation->epoint_id);
4067 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd endpoint.\n", ea_endpoint->ep_serial);
4068 *errstr = "No Call";
4071 if (!epoint->ep_portlist)
4073 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not port.\n", ea_endpoint->ep_serial);
4074 *errstr = "No Call";
4077 *port = find_port_id(epoint->ep_portlist->port_id);
4080 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has an none existing port.\n", ea_endpoint->ep_serial);
4081 *errstr = "No Call";
4084 if (((*port)->p_type&PORT_CLASS_mISDN_MASK)!=PORT_CLASS_mISDN_DSS1) /* port is not external isdn */
4086 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not an external port.\n", ea_endpoint->ep_serial);
4087 *errstr = "No Ext Call";
4090 if ((*port)->p_state != PORT_STATE_CONNECT)
4092 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint's port is not in connected state.\n", ea_endpoint->ep_serial);
4093 *errstr = "No Ext Connect";
4099 void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsigned int port_id, int dir)
4101 const char *logtext = "unknown";
4104 switch(message_type)
4107 trace_header("SETUP", dir);
4108 if (dir == DIRECTION_OUT)
4109 add_trace("to", NULL, "CH(%lu)", port_id);
4110 if (dir == DIRECTION_IN)
4111 add_trace("from", NULL, "CH(%lu)", port_id);
4112 if (param->setup.callerinfo.extension[0])
4113 add_trace("extension", NULL, "%s", param->setup.callerinfo.extension);
4114 add_trace("caller id", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype, options.national, options.international));
4115 switch(param->setup.callerinfo.present)
4117 case INFO_PRESENT_RESTRICTED:
4118 add_trace("caller id", "present", "restricted");
4120 case INFO_PRESENT_ALLOWED:
4121 add_trace("caller id", "present", "allowed");
4124 add_trace("caller id", "present", "not available");
4126 if (param->setup.callerinfo.ntype2)
4128 add_trace("caller id2", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id2, param->setup.callerinfo.ntype2, options.national, options.international));
4129 switch(param->setup.callerinfo.present)
4131 case INFO_PRESENT_RESTRICTED:
4132 add_trace("caller id2", "present", "restricted");
4134 case INFO_PRESENT_ALLOWED:
4135 add_trace("caller id2", "present", "allowed");
4138 add_trace("caller id2", "present", "not available");
4141 if (param->setup.redirinfo.id[0])
4143 add_trace("redir'ing", "number", "%s", numberrize_callerinfo(param->setup.redirinfo.id, param->setup.redirinfo.ntype, options.national, options.international));
4144 switch(param->setup.redirinfo.present)
4146 case INFO_PRESENT_RESTRICTED:
4147 add_trace("redir'ing", "present", "restricted");
4149 case INFO_PRESENT_ALLOWED:
4150 add_trace("redir'ing", "present", "allowed");
4153 add_trace("redir'ing", "present", "not available");
4156 if (param->setup.dialinginfo.id[0])
4157 add_trace("dialing", NULL, "%s", param->setup.dialinginfo.id);
4158 if (param->setup.dialinginfo.display[0])
4159 add_trace("display", NULL, "%s", param->setup.dialinginfo.display);
4160 if (param->setup.dialinginfo.sending_complete)
4161 add_trace("complete", NULL, "true", param->setup.dialinginfo.sending_complete);
4165 case MESSAGE_OVERLAP:
4166 trace_header("SETUP ACKNOWLEDGE", dir);
4167 if (dir == DIRECTION_OUT)
4168 add_trace("to", NULL, "CH(%lu)", port_id);
4169 if (dir == DIRECTION_IN)
4170 add_trace("from", NULL, "CH(%lu)", port_id);
4174 case MESSAGE_PROCEEDING:
4175 trace_header("PROCEEDING", dir);
4176 if (dir == DIRECTION_OUT)
4177 add_trace("to", NULL, "CH(%lu)", port_id);
4178 if (dir == DIRECTION_IN)
4179 add_trace("from", NULL, "CH(%lu)", port_id);
4183 case MESSAGE_ALERTING:
4184 trace_header("ALERTING", dir);
4185 if (dir == DIRECTION_OUT)
4186 add_trace("to", NULL, "CH(%lu)", port_id);
4187 if (dir == DIRECTION_IN)
4188 add_trace("from", NULL, "CH(%lu)", port_id);
4192 case MESSAGE_CONNECT:
4193 trace_header("CONNECT", dir);
4194 if (dir == DIRECTION_OUT)
4195 add_trace("to", NULL, "CH(%lu)", port_id);
4196 if (dir == DIRECTION_IN)
4197 add_trace("from", NULL, "CH(%lu)", port_id);
4198 if (param->connectinfo.extension[0])
4199 add_trace("extension", NULL, "%s", param->connectinfo.extension);
4200 add_trace("connect id", "number", "%s", numberrize_callerinfo(param->connectinfo.id, param->connectinfo.ntype, options.national, options.international));
4201 switch(param->connectinfo.present)
4203 case INFO_PRESENT_RESTRICTED:
4204 add_trace("connect id", "present", "restricted");
4206 case INFO_PRESENT_ALLOWED:
4207 add_trace("connect id", "present", "allowed");
4210 add_trace("connect id", "present", "not available");
4212 if (param->connectinfo.display[0])
4213 add_trace("display", NULL, "%s", param->connectinfo.display);
4217 case MESSAGE_DISCONNECT:
4218 case MESSAGE_RELEASE:
4219 if (message_type == MESSAGE_DISCONNECT)
4220 trace_header("DISCONNECT", dir);
4222 trace_header("RELEASE", dir);
4223 if (dir == DIRECTION_OUT)
4224 add_trace("to", NULL, "CH(%lu)", port_id);
4225 if (dir == DIRECTION_IN)
4226 add_trace("from", NULL, "CH(%lu)", port_id);
4227 add_trace("cause", "value", "%d", param->disconnectinfo.cause);
4228 switch(param->disconnectinfo.location)
4231 add_trace("cause", "location", "0-User");
4233 case LOCATION_PRIVATE_LOCAL:
4234 add_trace("cause", "location", "1-Local-PBX");
4236 case LOCATION_PUBLIC_LOCAL:
4237 add_trace("cause", "location", "2-Local-Exchange");
4239 case LOCATION_TRANSIT:
4240 add_trace("cause", "location", "3-Transit");
4242 case LOCATION_PUBLIC_REMOTE:
4243 add_trace("cause", "location", "4-Remote-Exchange");
4245 case LOCATION_PRIVATE_REMOTE:
4246 add_trace("cause", "location", "5-Remote-PBX");
4248 case LOCATION_INTERNATIONAL:
4249 add_trace("cause", "location", "7-International-Exchange");
4251 case LOCATION_BEYOND:
4252 add_trace("cause", "location", "10-Beyond-Interworking");
4255 add_trace("cause", "location", "%d", param->disconnectinfo.location);
4257 if (param->disconnectinfo.display[0])
4258 add_trace("display", NULL, "%s", param->disconnectinfo.display);
4262 case MESSAGE_NOTIFY:
4263 switch(param->notifyinfo.notify)
4269 logtext = "USER_SUSPENDED";
4272 logtext = "BEARER_SERVICE_CHANGED";
4275 logtext = "USER_RESUMED";
4278 logtext = "CONFERENCE_ESTABLISHED";
4281 logtext = "CONFERENCE_DISCONNECTED";
4284 logtext = "OTHER_PARTY_ADDED";
4287 logtext = "ISOLATED";
4290 logtext = "REATTACHED";
4293 logtext = "OTHER_PARTY_ISOLATED";
4296 logtext = "OTHER_PARTY_REATTACHED";
4299 logtext = "OTHER_PARTY_SPLIT";
4302 logtext = "OTHER_PARTY_DISCONNECTED";
4305 logtext = "CONFERENCE_FLOATING";
4308 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
4311 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
4314 logtext = "CALL_IS_A_WAITING_CALL";
4317 logtext = "DIVERSION_ACTIVATED";
4320 logtext = "RESERVED_CT_1";
4323 logtext = "RESERVED_CT_2";
4326 logtext = "REVERSE_CHARGING";
4329 logtext = "REMOTE_HOLD";
4332 logtext = "REMOTE_RETRIEVAL";
4335 logtext = "CALL_IS_DIVERTING";
4338 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
4342 trace_header("NOTIFY", dir);
4343 if (dir == DIRECTION_OUT)
4344 add_trace("to", NULL, "CH(%lu)", port_id);
4345 if (dir == DIRECTION_IN)
4346 add_trace("from", NULL, "CH(%lu)", port_id);
4347 if (param->notifyinfo.notify)
4348 add_trace("indicator", NULL, "%s", logtext);
4349 if (param->notifyinfo.id[0])
4351 add_trace("redir'on", "number", "%s", numberrize_callerinfo(param->notifyinfo.id, param->notifyinfo.ntype, options.national, options.international));
4352 switch(param->notifyinfo.present)
4354 case INFO_PRESENT_RESTRICTED:
4355 add_trace("redir'on", "present", "restricted");
4357 case INFO_PRESENT_ALLOWED:
4358 add_trace("redir'on", "present", "allowed");
4361 add_trace("redir'on", "present", "not available");
4364 if (param->notifyinfo.display[0])
4365 add_trace("display", NULL, "%s", param->notifyinfo.display);
4369 case MESSAGE_INFORMATION:
4370 trace_header("INFORMATION", dir);
4371 if (dir == DIRECTION_OUT)
4372 add_trace("to", NULL, "CH(%lu)", port_id);
4373 if (dir == DIRECTION_IN)
4374 add_trace("from", NULL, "CH(%lu)", port_id);
4375 if (param->information.id[0])
4376 add_trace("dialing", NULL, "%s", param->information.id);
4377 if (param->information.display[0])
4378 add_trace("display", NULL, "%s", param->information.display);
4379 if (param->information.sending_complete)
4380 add_trace("complete", NULL, "true", param->information.sending_complete);
4384 case MESSAGE_FACILITY:
4385 trace_header("FACILITY", dir);
4386 if (dir == DIRECTION_OUT)
4387 add_trace("to", NULL, "CH(%lu)", port_id);
4388 if (dir == DIRECTION_IN)
4389 add_trace("from", NULL, "CH(%lu)", port_id);
4394 trace_header("TONE", dir);
4395 if (dir == DIRECTION_OUT)
4396 add_trace("to", NULL, "CH(%lu)", port_id);
4397 if (dir == DIRECTION_IN)
4398 add_trace("from", NULL, "CH(%lu)", port_id);
4399 if (param->tone.name[0])
4401 add_trace("directory", NULL, "%s", param->tone.dir[0]?param->tone.dir:"default");
4402 add_trace("name", NULL, "%s", param->tone.name);
4404 add_trace("off", NULL, NULL);
4408 case MESSAGE_SUSPEND:
4409 case MESSAGE_RESUME:
4410 if (message_type == MESSAGE_SUSPEND)
4411 trace_header("SUSPEND", dir);
4413 trace_header("RESUME", dir);
4414 if (dir == DIRECTION_OUT)
4415 add_trace("to", NULL, "CH(%lu)", port_id);
4416 if (dir == DIRECTION_IN)
4417 add_trace("from", NULL, "CH(%lu)", port_id);
4418 if (param->parkinfo.len)
4419 add_trace("length", NULL, "%d", param->parkinfo.len);
4424 case MESSAGE_BCHANNEL:
4425 trace_header("BCHANNEL", dir);
4426 switch(param->bchannel.type)
4428 case BCHANNEL_REQUEST:
4429 add_trace("type", NULL, "request");
4431 case BCHANNEL_ASSIGN:
4432 add_trace("type", NULL, "assign");
4434 case BCHANNEL_ASSIGN_ACK:
4435 add_trace("type", NULL, "assign_ack");
4437 case BCHANNEL_REMOVE:
4438 add_trace("type", NULL, "remove");
4440 case BCHANNEL_REMOVE_ACK:
4441 add_trace("type", NULL, "remove_ack");
4444 if (param->bchannel.addr)
4445 add_trace("address", NULL, "%x", param->bchannel.addr);
4451 PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message_type);
4455 void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cause, int location, const char *display)
4457 struct lcr_msg *message;
4461 if (!portlist->port_id)
4464 if (!e_connectedmode)
4466 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT);
4467 message->param.disconnectinfo.cause = cause;
4468 message->param.disconnectinfo.location = location;
4470 SCPY(message->param.disconnectinfo.display, display);
4472 SCPY(message->param.disconnectinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4475 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
4477 SCPY(message->param.notifyinfo.display, display);
4479 SCPY(message->param.notifyinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4481 message_put(message);
4482 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);