1 /*****************************************************************************\
3 ** Linux Call Router **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
8 ** The EndpointAppPBX implements PBX4Linux **
10 \*****************************************************************************/
15 class EndpointAppPBX *apppbx_first = NULL;
17 int action_timeout(struct lcr_timer *timer, void *instance, int index);
18 int match_timeout(struct lcr_timer *timer, void *instance, int index);
19 int redial_timeout(struct lcr_timer *timer, void *instance, int index);
20 int powerdial_timeout(struct lcr_timer *timer, void *instance, int index);
21 int cfnr_timeout(struct lcr_timer *timer, void *instance, int index);
22 int cfnr_call_timeout(struct lcr_timer *timer, void *instance, int index);
23 int password_timeout(struct lcr_timer *timer, void *instance, int index);
24 int callback_timeout(struct lcr_timer *timer, void *instance, int index);
27 * EndpointAppPBX constructor
29 EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint, int origin) : EndpointApp(epoint, origin)
31 class EndpointAppPBX **apppointer;
33 memset(&e_crypt_handler, 0, sizeof(e_crypt_handler));
34 add_timer(&e_crypt_handler, crypt_handler, this, 0);
35 memset(&e_vbox_refresh, 0, sizeof(e_vbox_refresh));
36 add_timer(&e_vbox_refresh, vbox_refresh, this, 0);
37 memset(&e_action_timeout, 0, sizeof(e_action_timeout));
38 add_timer(&e_action_timeout, action_timeout, this, 0);
39 memset(&e_match_timeout, 0, sizeof(e_match_timeout));
40 add_timer(&e_match_timeout, match_timeout, this, 0);
41 memset(&e_redial_timeout, 0, sizeof(e_redial_timeout));
42 add_timer(&e_redial_timeout, redial_timeout, this, 0);
43 memset(&e_powerdial_timeout, 0, sizeof(e_powerdial_timeout));
44 add_timer(&e_powerdial_timeout, powerdial_timeout, this, 0);
45 memset(&e_cfnr_timeout, 0, sizeof(e_cfnr_timeout));
46 add_timer(&e_cfnr_timeout, cfnr_timeout, this, 0);
47 memset(&e_cfnr_call_timeout, 0, sizeof(e_cfnr_call_timeout));
48 add_timer(&e_cfnr_call_timeout, cfnr_call_timeout, this, 0);
49 memset(&e_callback_timeout, 0, sizeof(e_callback_timeout));
50 add_timer(&e_callback_timeout, callback_timeout, this, 0);
51 memset(&e_password_timeout, 0, sizeof(e_password_timeout));
52 add_timer(&e_password_timeout, password_timeout, this, 0);
55 /* add application to chain */
57 apppointer = &apppbx_first;
59 apppointer = &((*apppointer)->next);
63 memset(&e_ext, 0, sizeof(struct extension));
64 // *************** NOTE: also change value in read_extension() **************
65 e_ext.rights = 4; /* international */
66 e_ext.rx_gain = e_ext.tx_gain = 0;
67 e_state = EPOINT_STATE_IDLE;
68 e_ext.number[0] = '\0';
69 e_extension_interface[0] = '\0';
70 memset(&e_callerinfo, 0, sizeof(struct caller_info));
71 memset(&e_dialinginfo, 0, sizeof(struct dialing_info));
72 memset(&e_connectinfo, 0, sizeof(struct connect_info));
73 memset(&e_redirinfo, 0, sizeof(struct redir_info));
74 memset(&e_capainfo, 0, sizeof(struct capa_info));
77 e_ruleset = ruleset_main;
79 e_rule = e_ruleset->rule_first;
82 e_match_to_action = NULL;
84 e_extdialing = e_dialinginfo.id;
88 // e_join_tone[0] = e_hold_tone[0] = '\0';
89 e_join_pattern /*= e_hold_pattern*/ = 0;
91 e_adminid = 0; // will be set, if call was initiated via admin socket
94 e_cbdialing[0] = '\0';
97 memset(&e_callbackinfo, 0, sizeof(struct caller_info));
103 e_multipoint_cause = 0;
104 e_multipoint_location = 0;
105 e_dialing_queue[0] = '\0';
107 e_crypt_state = CM_ST_NULL;
108 e_crypt_keyengine_busy = 0;
109 e_crypt_info[0] = '\0';
112 e_tx_state = NOTIFY_STATE_ACTIVE;
113 e_rx_state = NOTIFY_STATE_ACTIVE;
114 e_join_cause = e_join_location = 0;
115 /*********************************
116 *********************************
117 ********* ATTENTION *************
118 *********************************
119 *********************************/
120 /* if you add new values, that must be initialized, also check if they must
121 * be initialized when doing callback
127 * EpointAppPBX destructor
129 EndpointAppPBX::~EndpointAppPBX(void)
131 class EndpointAppPBX *temp, **tempp;
133 del_timer(&e_crypt_handler);
134 del_timer(&e_vbox_refresh);
135 del_timer(&e_action_timeout);
136 del_timer(&e_match_timeout);
137 del_timer(&e_redial_timeout);
138 del_timer(&e_powerdial_timeout);
139 del_timer(&e_cfnr_timeout);
140 del_timer(&e_cfnr_call_timeout);
141 del_timer(&e_callback_timeout);
142 del_timer(&e_password_timeout);
146 tempp = &apppbx_first;
155 FATAL("Endpoint not in endpoint's list.\n");
162 * trace header for application
164 void EndpointAppPBX::trace_header(const char *name, int direction)
168 char msgtext[sizeof(_trace.name)];
172 /* init trace with given values */
175 numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype, options.national, options.international),
179 ea_endpoint->ep_serial,
186 /* set new endpoint state
188 void EndpointAppPBX::new_state(int state)
191 if (e_state != state) {
192 trace_header("NEW STATE", DIRECTION_NONE);
193 add_trace("state", "old", "%s", state_name[e_state]);
194 add_trace("state", "new", "%s", state_name[state]);
202 /* release join and port (as specified)
204 void EndpointAppPBX::release(int release, int joinlocation, int joincause, int portlocation, int portcause, int force)
206 struct port_list *portlist;
207 struct lcr_msg *message;
210 /* message to test call */
211 admin_call_response(e_adminid, ADMIN_CALL_RELEASE, "", joincause, joinlocation, 0);
213 /* if a release is pending */
214 if (release==RELEASE_JOIN || release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY) {
215 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): do pending release (joincause %d location %d)\n", ea_endpoint->ep_serial, joincause, joinlocation);
216 if (ea_endpoint->ep_join_id) {
217 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_RELEASE);
218 message->param.disconnectinfo.cause = joincause;
219 message->param.disconnectinfo.location = joinlocation;
220 message_put(message);
221 ea_endpoint->ep_join_id = 0;
225 if (release != RELEASE_PORT_JOINONLY) {
227 join_release(e_hold_id, ea_endpoint->ep_serial, 1, joinlocation, joincause);
232 if (release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY) {
233 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release (portcause %d portlocation)\n", ea_endpoint->ep_serial, portcause, portlocation);
234 while((portlist = ea_endpoint->ep_portlist)) {
235 if (portlist->port_id) {
236 SPRINT(cause, "cause_%02x", portcause);
237 set_tone(portlist, cause);
238 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
239 message->param.disconnectinfo.cause = portcause;
240 message->param.disconnectinfo.location = portlocation;
241 message->param.disconnectinfo.force = force; // set, if port should release imediately
242 message_put(message);
243 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
245 ea_endpoint->free_portlist(portlist);
248 /* if callback is enabled, call back with the given caller id */
249 if (e_callback_timeout.active) {
250 /* reset some stuff */
251 new_state(EPOINT_STATE_IDLE);
252 memset(&e_connectinfo, 0, sizeof(struct connect_info));
253 memset(&e_redirinfo, 0, sizeof(struct redir_info));
254 e_start = e_stop = 0;
255 e_ruleset = ruleset_main;
257 e_rule = e_ruleset->rule_first;
259 unsched_timer(&e_action_timeout);
260 unsched_timer(&e_match_timeout);
261 unsched_timer(&e_cfnr_timeout);
262 unsched_timer(&e_cfnr_call_timeout);
263 e_match_to_action = NULL;
265 e_extdialing = e_dialinginfo.id;
271 e_multipoint_cause = 0;
272 e_multipoint_location = 0;
273 e_dialing_queue[0] = '\0';
275 e_crypt_state = CM_ST_NULL;
276 e_crypt_keyengine_busy = 0;
277 e_crypt_info[0] = '\0';
281 e_tx_state = NOTIFY_STATE_ACTIVE;
282 e_rx_state = NOTIFY_STATE_ACTIVE;
283 e_join_cause = e_join_location = 0;
285 /* the caller info of the callback user */
286 memcpy(&e_callbackinfo, &e_callerinfo, sizeof(e_callbackinfo));
287 memset(&e_dialinginfo, 0, sizeof(e_dialinginfo));
288 /* create dialing by callerinfo */
289 if (e_ext.number[0] && e_extension_interface[0]) {
290 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to internal: %s interface %s\n", ea_endpoint->ep_serial, e_ext.number, e_extension_interface);
291 /* create callback to the current terminal */
292 SCPY(e_dialinginfo.id, e_ext.number);
293 SCPY(e_dialinginfo.interfaces, e_extension_interface);
294 e_dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
295 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
298 SCPY(e_dialinginfo.id, e_cbto);
300 /* numberrize caller id and use it to dial to the callback */
301 SCPY(e_dialinginfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype, options.national, options.international));
303 e_dialinginfo.itype = INFO_ITYPE_ISDN;
304 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
305 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to external: %s\n", ea_endpoint->ep_serial, e_dialinginfo.id);
310 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release of epoint itself.\n", ea_endpoint->ep_serial);
311 if (--ea_endpoint->ep_use <= 0) /* when e_lock is 0, the endpoint will be deleted */
312 trigger_work(&ea_endpoint->ep_delete);
318 /* cancel callerid if restricted, unless anon-ignore is enabled at extension or port is of type external (so called police gets caller id :)*/
319 void apply_callerid_restriction(struct extension *ext, char *id, int *ntype, int *present, int *screen, char *extension, char *name)
321 PDEBUG(DEBUG_EPOINT, "id='%s' ntype=%d present=%d screen=%d extension='%s' name='%s'\n", (id)?id:"NULL", (ntype)?*ntype:-1, (present)?*present:-1, (screen)?*screen:-1, (extension)?extension:"NULL", (name)?name:"NULL");
323 /* caller id is not restricted, so we do nothing */
324 if (*present != INFO_PRESENT_RESTRICTED)
327 /* only extensions are restricted */
331 /* if we enabled anonymouse ignore */
332 if (ext->anon_ignore)
335 /* else we remove the caller id */
339 *ntype = INFO_NTYPE_UNKNOWN;
341 // *screen = INFO_SCREEN_USER;
342 // maybe we should not make voip address anonymous
345 // maybe it's no fraud to present extension id
347 // extension[0] = '\0';
352 /* used display message to display callerid as available */
353 char *EndpointAppPBX::apply_callerid_display(const char *id, int itype, int ntype, int present, int screen, const char *extension, const char *name)
355 static char display[81];
358 const char *cid = numberrize_callerinfo(id, ntype, options.national, options.international);
360 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) id='%s' itype=%d ntype=%d present=%d screen=%d extension='%s' name='%s'\n", ea_endpoint->ep_serial, (id)?id:"NULL", itype, ntype, present, screen, (extension)?extension:"NULL", (name)?name:"NULL");
369 /* NOTE: is caller is is not available for this extesion, it has been removed by apply_callerid_restriction already */
371 /* internal extension's caller id */
372 if (extension[0] && e_ext.display_int) {
374 SCAT(display, extension);
377 if (itype == INFO_ITYPE_VBOX)
378 SCAT(display, "(vbox)");
380 SCAT(display, "(int)");
383 /* external caller id */
384 if (!extension[0] && e_ext.display_ext) {
387 if (present == INFO_PRESENT_RESTRICTED)
388 SCAT(display, "anonymous");
390 SCAT(display, "unknown");
397 /* display if callerid is anonymouse but available due anon-ignore */
398 if (e_ext.display_anon && present==INFO_PRESENT_RESTRICTED) {
400 SCAT(display, "unknown");
403 SCAT(display, " anon");
406 /* display if callerid is anonymouse but available due anon-ignore */
407 if (e_ext.display_fake && screen==INFO_SCREEN_USER && ntype!=INFO_NTYPE_NOTPRESENT) {
410 if (present == INFO_PRESENT_RESTRICTED)
411 SCAT(display, "anonymous");
413 SCAT(display, "unknown");
418 SCAT(display, " fake");
422 if (name[0] && e_ext.display_name) {
423 if (!display[0] && cid[0])
434 * uses the current state to notify activity
436 void EndpointAppPBX::notify_active(void)
438 struct port_list *portlist = ea_endpoint->ep_portlist;
439 struct lcr_msg *message;
443 case NOTIFY_STATE_ACTIVE:
444 /* we are already active, so we don't do anything */
447 case NOTIFY_STATE_SUSPEND:
448 notify = INFO_NOTIFY_USER_RESUMED;
450 set_tone(portlist, NULL);
451 portlist = portlist->next;
453 portlist = ea_endpoint->ep_portlist;
456 case NOTIFY_STATE_HOLD:
457 notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
459 set_tone(portlist, NULL);
460 portlist = portlist->next;
462 portlist = ea_endpoint->ep_portlist;
465 case NOTIFY_STATE_CONFERENCE:
466 notify = INFO_NOTIFY_CONFERENCE_DISCONNECTED;
468 set_tone(portlist, NULL);
469 portlist = portlist->next;
471 portlist = ea_endpoint->ep_portlist;
475 PERROR("unknown e_tx_state = %d\n", e_tx_state);
480 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
481 message->param.notifyinfo.notify = notify;
482 message_put(message);
483 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
484 portlist = portlist->next;
490 * keypad functions during call. one example to use this is to put a call on hold or start a conference
492 void EndpointAppPBX::keypad_function(char digit)
495 /* we must be in a call, in order to send messages to the call */
496 if (e_ext.number[0] == '\0') {
497 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) IGNORING keypad received not from extension.\n", ea_endpoint->ep_serial);
502 /* join conference */
504 if (ea_endpoint->ep_join_id == 0) {
505 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad received during connect but not during a call.\n", ea_endpoint->ep_serial);
508 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join call with call on hold\n", ea_endpoint->ep_serial);
514 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) shared key encryption selected.\n", ea_endpoint->ep_serial);
518 /* crypt key-exchange */
520 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) key exchange encryption selected.\n", ea_endpoint->ep_serial);
526 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) encryption off selected.\n", ea_endpoint->ep_serial);
531 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) unsupported keypad digit '%c'.\n", ea_endpoint->ep_serial, digit);
536 /* set tone pattern for port */
537 void EndpointAppPBX::set_tone(struct port_list *portlist, const char *tone)
539 struct lcr_msg *message;
544 /* store for suspended processes */
548 if (e_join_pattern /* pattern are provided */
549 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_SETUP)
550 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_OVERLAP)
551 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_IN_PROCEEDING)
552 && !(e_ext.own_alerting && e_state == EPOINT_STATE_IN_ALERTING)
553 && !(e_ext.own_cause && e_state == EPOINT_STATE_IN_DISCONNECT)
554 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_SETUP)
555 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_OVERLAP)
556 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_OUT_PROCEEDING)
557 && !(e_ext.own_alerting && e_state == EPOINT_STATE_OUT_ALERTING)
558 && !(e_ext.own_cause && e_state == EPOINT_STATE_OUT_DISCONNECT)
559 && tone[0] && !!strncmp(tone,"crypt_*",6)) {
560 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) tone not provided since patterns are available\n", ea_endpoint->ep_serial);
565 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_TONE);
566 SCPY(message->param.tone.dir, e_ext.tones_dir);
567 SCPY(message->param.tone.name, tone);
568 message_put(message);
569 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
571 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port to notify tone.\n", ea_endpoint->ep_serial);
578 * hunts an mISDNport that is available for an outgoing call
579 * if no ifname was given, any interface that is not an extension
582 struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel)
584 struct interface *interface;
585 struct interface_port *ifport, *ifport_start;
586 struct select_channel *selchannel;
587 struct mISDNport *mISDNport;
589 int there_is_an_external = 0;
591 interface = interface_first;
593 /* first find the given interface or, if not given, one with no extension */
596 if (!there_is_an_external && !(ifname && ifname[0])) {
597 trace_header("CHANNEL SELECTION (no external interface specified)", DIRECTION_NONE);
598 add_trace("info", NULL, "Add 'extern' parameter to interface.conf.");
604 /* check for given interface */
605 if (ifname && ifname[0]) {
606 if (!strcasecmp(interface->name, ifname)) {
607 /* found explicit interface */
608 trace_header("CHANNEL SELECTION (found given interface)", DIRECTION_NONE);
609 add_trace("interface", NULL, "%s", ifname);
615 if (interface->external) {
616 there_is_an_external = 1;
617 /* found non extension */
618 trace_header("CHANNEL SELECTION (found external interface)", DIRECTION_NONE);
619 add_trace("interface", NULL, "%s", interface->name);
625 interface = interface->next;
629 /* see if interface has ports */
630 if (!interface->ifport) {
632 trace_header("CHANNEL SELECTION (active ports, skipping)", DIRECTION_NONE);
633 add_trace("interface", NULL, "%s", interface->name);
635 interface = interface->next;
639 /* select port by algorithm */
640 ifport_start = interface->ifport;
642 if (interface->hunt == HUNT_ROUNDROBIN) {
643 while(ifport_start->next && index<interface->hunt_next) {
644 ifport_start = ifport_start->next;
647 trace_header("CHANNEL SELECTION (starting round-robin)", DIRECTION_NONE);
648 add_trace("port", NULL, "%d", ifport_start->portnum);
649 add_trace("position", NULL, "%d", index);
654 ifport = ifport_start;
657 /* see if port is available */
658 if (!ifport->mISDNport) {
659 trace_header("CHANNEL SELECTION (port not available, skipping)", DIRECTION_NONE);
660 add_trace("port", NULL, "%d", ifport->portnum);
661 add_trace("position", NULL, "%d", index);
665 mISDNport = ifport->mISDNport;
667 /* see if port is administratively blocked */
669 trace_header("CHANNEL SELECTION (port blocked by admin, skipping)", DIRECTION_NONE);
670 add_trace("port", NULL, "%d", ifport->portnum);
671 add_trace("position", NULL, "%d", index);
676 /* see if link is up on PTP*/
677 if (mISDNport->l2hold && mISDNport->l2link<1) {
678 trace_header("CHANNEL SELECTION (port's layer 2 is down, skipping)", DIRECTION_NONE);
679 add_trace("port", NULL, "%d", ifport->portnum);
680 add_trace("position", NULL, "%d", index);
685 /* check for channel form selection list */
688 if (mISDNport->ss5) {
690 port = ss5_hunt_line(mISDNport);
692 *channel = port->p_m_b_channel;
693 trace_header("CHANNEL SELECTION (selecting SS5 channel)", DIRECTION_NONE);
694 add_trace("port", NULL, "%d", ifport->portnum);
695 add_trace("position", NULL, "%d", index);
696 add_trace("channel", NULL, "%d", *channel);
702 selchannel = ifport->out_channel;
704 switch(selchannel->channel) {
705 case CHANNEL_FREE: /* free channel */
706 if (mISDNport->b_reserved >= mISDNport->b_num)
707 break; /* all channel in use or reserverd */
710 while(i < mISDNport->b_num) {
711 if (mISDNport->b_port[i] == NULL) {
712 *channel = i+1+(i>=15);
713 trace_header("CHANNEL SELECTION (selecting free channel)", DIRECTION_NONE);
714 add_trace("port", NULL, "%d", ifport->portnum);
715 add_trace("position", NULL, "%d", index);
716 add_trace("channel", NULL, "%d", *channel);
724 trace_header("CHANNEL SELECTION (no channel is 'free')", DIRECTION_NONE);
725 add_trace("port", NULL, "%d", ifport->portnum);
726 add_trace("position", NULL, "%d", index);
730 case CHANNEL_ANY: /* don't ask for channel */
731 if (mISDNport->b_reserved >= mISDNport->b_num) {
732 trace_header("CHANNEL SELECTION (cannot ask for 'any' channel, all reserved)", DIRECTION_NONE);
733 add_trace("port", NULL, "%d", ifport->portnum);
734 add_trace("position", NULL, "%d", index);
735 add_trace("total", NULL, "%d", mISDNport->b_num);
736 add_trace("reserved", NULL, "%d", mISDNport->b_reserved);
738 break; /* all channel in use or reserverd */
740 trace_header("CHANNEL SELECTION (using 'any' channel)", DIRECTION_NONE);
741 add_trace("port", NULL, "%d", ifport->portnum);
742 add_trace("position", NULL, "%d", index);
744 *channel = CHANNEL_ANY;
747 case CHANNEL_NO: /* call waiting */
748 trace_header("CHANNEL SELECTION (using 'no' channel, call-waiting)", DIRECTION_NONE);
749 add_trace("port", NULL, "%d", ifport->portnum);
750 add_trace("position", NULL, "%d", index);
752 *channel = CHANNEL_NO;
756 if (selchannel->channel<1 || selchannel->channel==16) {
757 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
758 add_trace("port", NULL, "%d", ifport->portnum);
759 add_trace("position", NULL, "%d", index);
760 add_trace("channel", NULL, "%d", selchannel->channel);
762 break; /* invalid channels */
764 i = selchannel->channel-1-(selchannel->channel>=17);
765 if (i >= mISDNport->b_num) {
766 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
767 add_trace("port", NULL, "%d", ifport->portnum);
768 add_trace("position", NULL, "%d", index);
769 add_trace("channel", NULL, "%d", selchannel->channel);
770 add_trace("channels", NULL, "%d", mISDNport->b_num);
772 break; /* channel not in port */
774 if (mISDNport->b_port[i] == NULL) {
775 *channel = selchannel->channel;
776 trace_header("CHANNEL SELECTION (selecting given channel)", DIRECTION_NONE);
777 add_trace("port", NULL, "%d", ifport->portnum);
778 add_trace("position", NULL, "%d", index);
779 add_trace("channel", NULL, "%d", *channel);
786 break; /* found channel */
787 selchannel = selchannel->next;
791 /* if channel was found, return mISDNport and channel */
793 /* setting next port to start next time */
794 if (interface->hunt == HUNT_ROUNDROBIN) {
798 interface->hunt_next = index;
804 trace_header("CHANNEL SELECTION (skipping, no channel found)", DIRECTION_NONE);
805 add_trace("port", NULL, "%d", ifport->portnum);
806 add_trace("position", NULL, "%d", index);
810 /* go next port, until all ports are checked */
812 ifport = ifport->next;
815 ifport = interface->ifport;
817 if (ifport != ifport_start)
821 interface = interface->next;
825 return(NULL); /* no port found */
828 /* outgoing setup to port(s)
829 * ports will be created and a setup is sent if everything is ok. otherwhise
830 * the endpoint is destroyed.
832 void EndpointAppPBX::out_setup(int cfnr)
834 struct dialing_info dialinginfo;
836 struct port_list *portlist;
837 struct lcr_msg *message;
839 int cause = CAUSE_RESSOURCEUNAVAIL;
842 struct mISDNport *mISDNport;
845 class EndpointAppPBX *atemp;
846 // char allowed_ports[256];
848 char ifname[sizeof(e_ext.interfaces)],
850 struct port_settings port_settings;
853 int mode = B_MODE_TRANSPARENT;
854 struct admin_list *admin;
856 /* set bchannel mode */
857 mode = e_capainfo.source_mode;
859 /* create settings for creating port */
860 memset(&port_settings, 0, sizeof(port_settings));
862 SCPY(port_settings.tones_dir, e_ext.tones_dir);
864 SCPY(port_settings.tones_dir, options.tones_dir);
865 port_settings.no_seconds = e_ext.no_seconds;
867 /* 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 */
869 /* check what dialinginfo.itype we got */
870 switch(e_dialinginfo.itype) {
871 /* *********************** call to extension or vbox */
872 case INFO_ITYPE_ISDN_EXTENSION:
873 /* check if we deny incoming calls when we use an extension */
874 if (e_ext.noknocking) {
875 atemp = apppbx_first;
878 if (!strcmp(atemp->e_ext.number, e_ext.number))
883 PERROR("EPOINT(%d) noknocking and currently a call\n", ea_endpoint->ep_serial);
884 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYSPE_ join, port */
885 return; /* must exit here */
888 /* FALL THROUGH !!!! */
889 case INFO_ITYPE_VBOX:
890 /* get dialed extension's info */
891 // SCPY(exten, e_dialinginfo.id);
892 // if (strchr(exten, ','))
893 // *strchr(exten, ',') = '\0';
894 // if (!read_extension(&e_ext, exten))
895 if (!read_extension(&e_ext, e_dialinginfo.id)) {
896 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) extension %s not configured\n", ea_endpoint->ep_serial, e_dialinginfo.id);
897 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
898 return; /* must exit here */
900 e_dialinginfo.sending_complete = 1;
902 if (e_dialinginfo.itype == INFO_ITYPE_VBOX) {
903 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing directly to VBOX\n", ea_endpoint->ep_serial);
908 /* string from unconditional call forward (cfu) */
911 /* present to forwarded party */
912 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) */
922 class EndpointAppPBX *checkapp = apppbx_first;
924 if (checkapp != this) { /* any other endpoint except our own */
925 if (!strcmp(checkapp->e_ext.number, e_ext.number)) {
926 /* present to forwarded party */
927 if (e_ext.anon_ignore && e_callerinfo.id[0]) {
928 e_callerinfo.present = INFO_PRESENT_ALLOWED;
930 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
934 checkapp = checkapp->next;
938 /* string from no-response call forward (cfnr) */
941 /* when cfnr is done, out_setup() will setup the call */
943 /* present to forwarded party */
944 if (e_ext.anon_ignore && e_callerinfo.id[0]) {
945 e_callerinfo.present = INFO_PRESENT_ALLOWED;
949 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH)) {
950 schedule_timer(&e_cfnr_timeout, e_ext.cfnr_delay, 0);
951 schedule_timer(&e_cfnr_call_timeout, e_ext.cfnr_delay + 1, 0); /* call one second after release */
952 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);
956 /* call to all internal interfaces */
957 p = e_ext.interfaces;
958 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) generating multiple joins for extension %s to interfaces %s\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
961 while(*p!=',' && *p!='\0')
966 /* found interface */
967 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
968 /* hunt for mISDNport and create Port */
969 mISDNport = hunt_port(ifname, &channel);
971 trace_header("INTERFACE (not found or busy)", DIRECTION_NONE);
972 add_trace("interface", NULL, "%s", ifname);
976 /* creating INTERNAL port */
977 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
980 port = ss5_hunt_line(mISDNport);
984 if (mISDNport->gsm_bs)
985 port = new Pgsm_bs(PORT_TYPE_GSM_BS_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
989 if (mISDNport->gsm_ms)
990 port = new Pgsm_ms(PORT_TYPE_GSM_MS_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
994 if (mISDNport->ifport->interface->sip)
995 port = new Psip(PORT_TYPE_SIP_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode, mISDNport->ifport->interface);
998 if (mISDNport->ifport->remote) {
1001 if (admin->remote_name[0] && !strcmp(admin->remote_name, mISDNport->ifport->remote_app))
1003 admin = admin->next;
1006 trace_header("INTERFACE (remote not connected)", DIRECTION_NONE);
1007 add_trace("application", NULL, "%s", mISDNport->ifport->remote_app);
1011 port = new Premote(PORT_TYPE_REMOTE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode, admin->sock);
1013 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);
1015 FATAL("Failed to create Port instance\n");
1016 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
1017 memset(&dialinginfo, 0, sizeof(dialinginfo));
1018 SCPY(dialinginfo.id, e_dialinginfo.id);
1019 dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
1020 dialinginfo.ntype = e_dialinginfo.ntype;
1021 /* create port_list relation */
1022 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
1024 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1026 goto check_anycall_intern;
1028 /* directory.list */
1029 if (e_callerinfo.id[0] && e_ext.display_name) {
1030 dirname = parse_directory(e_callerinfo.id, e_callerinfo.ntype);
1032 SCPY(e_callerinfo.name, dirname);
1034 // dss1 = (class Pdss1 *)port;
1036 //printf("INTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1037 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1038 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1039 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1040 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1041 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1042 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1043 //terminal if (e_dialinginfo.id)
1044 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1045 /* handle restricted caller ids */
1046 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);
1047 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);
1048 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);
1049 /* display callerid if desired for extension */
1050 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));
1051 //printf("\n\ndisplay = %s\n\n\n",message->param.setup.callerinfo.display);
1052 /* use cnip, if enabld */
1053 // if (!e_ext.centrex)
1054 // message->param.setup.callerinfo.name[0] = '\0';
1055 /* screen clip if prefix is required */
1056 if (message->param.setup.callerinfo.id[0] && e_ext.clip_prefix[0]) {
1057 SCPY(message->param.setup.callerinfo.id, e_ext.clip_prefix);
1058 SCAT(message->param.setup.callerinfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype, options.national, options.international));
1059 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1061 if (message->param.setup.callerinfo.id2[0] && e_ext.clip_prefix[0]) {
1062 SCPY(message->param.setup.callerinfo.id2, e_ext.clip_prefix);
1063 SCAT(message->param.setup.callerinfo.id2, numberrize_callerinfo(e_callerinfo.id2,e_callerinfo.ntype2, options.national, options.international));
1064 message->param.setup.callerinfo.ntype2 = INFO_NTYPE_UNKNOWN;
1066 /* use internal caller id */
1067 if (e_callerinfo.extension[0] && (message->param.setup.callerinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore)) {
1068 SCPY(message->param.setup.callerinfo.id, e_callerinfo.extension);
1069 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1070 message->param.setup.callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
1072 message_put(message);
1073 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1077 /* string from parallel call forward (cfp) */
1080 if (e_ext.anon_ignore && e_callerinfo.id[0]) {
1081 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1082 e_callerinfo.present2 = INFO_PRESENT_ALLOWED;
1086 vbox_only: /* entry point for answering machine only */
1087 cfu_only: /* entry point for cfu */
1088 cfb_only: /* entry point for cfb */
1089 cfnr_only: /* entry point for cfnr */
1090 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call extension %s for external destiantion(s) '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
1094 /* only if vbox should be dialed, and terminal is given */
1095 if (!strcmp(p, "vbox") && e_ext.number[0]) {
1096 /* go to the end of p */
1099 /* answering vbox call */
1100 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) answering machine\n", ea_endpoint->ep_serial);
1102 if (!(port = new VBoxPort(PORT_TYPE_VBOX_OUT, &port_settings)))
1103 FATAL("No memory for VBOX Port instance\n");
1104 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocated port %s\n", ea_endpoint->ep_serial, port->p_name);
1105 UCPY(cfp, e_ext.number); /* cfp or any other direct forward/vbox */
1108 while(*p!=',' && *p!='\0')
1113 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cfp external %s\n", ea_endpoint->ep_serial, cfp);
1114 /* hunt for mISDNport and create Port */
1115 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1117 /* creating EXTERNAL port*/
1118 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1121 port = ss5_hunt_line(mISDNport);
1124 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);
1126 FATAL("No memory for Port instance\n");
1127 earlyb = mISDNport->earlyb;
1130 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1131 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1136 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port found or created, which is idle.\n", ea_endpoint->ep_serial);
1137 goto check_anycall_intern;
1139 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found or created port %s\n", ea_endpoint->ep_serial, port->p_name);
1140 memset(&dialinginfo, 0, sizeof(dialinginfo));
1141 SCPY(dialinginfo.id, cfp);
1142 dialinginfo.itype = INFO_ITYPE_ISDN;
1143 dialinginfo.ntype = e_dialinginfo.ntype;
1144 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
1146 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1148 goto check_anycall_intern;
1150 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1151 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1152 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1153 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1154 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1155 /* if clip is hidden */
1156 if (e_ext.clip==CLIP_HIDE && port->p_type!=PORT_TYPE_VBOX_OUT) {
1157 SCPY(message->param.setup.callerinfo.id, e_ext.callerid);
1158 SCPY(message->param.setup.callerinfo.extension, e_ext.number);
1159 message->param.setup.callerinfo.ntype = e_ext.callerid_type;
1160 message->param.setup.callerinfo.present = e_ext.callerid_present;
1161 message->param.setup.callerinfo.ntype = INFO_NTYPE_NOTPRESENT;
1163 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1164 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1165 //terminal if (e_dialinginfo.id)
1166 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1167 /* handle restricted caller ids */
1168 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);
1169 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);
1170 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);
1171 /* display callerid if desired for extension */
1172 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));
1173 message_put(message);
1174 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1178 check_anycall_intern:
1179 /* now we have all ports created */
1181 trace_header("INTERFACE (no extension's interface)", DIRECTION_NONE);
1183 if (!ea_endpoint->ep_join_id)
1185 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
1186 return; /* must exit here */
1190 /* *********************** external call */
1192 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: called='%s' keypad='%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id, e_dialinginfo.keypad);
1193 /* call to extenal interfaces */
1194 if (e_dialinginfo.keypad[0])
1195 p = e_dialinginfo.keypad;
1197 p = e_dialinginfo.id;
1200 while(*p!=',' && *p!='\0')
1201 SCCAT(number, *p++);
1205 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");
1206 /* hunt for mISDNport and create Port */
1207 /* hunt for mISDNport and create Port */
1208 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1210 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1211 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1213 goto check_anycall_extern;
1215 /* creating EXTERNAL port*/
1216 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1219 port = ss5_hunt_line(mISDNport);
1223 if (mISDNport->gsm_bs)
1224 port = new Pgsm_bs(PORT_TYPE_GSM_BS_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
1228 if (mISDNport->gsm_ms)
1229 port = new Pgsm_ms(PORT_TYPE_GSM_MS_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
1233 if (mISDNport->ifport->interface->sip)
1234 port = new Psip(PORT_TYPE_SIP_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode, mISDNport->ifport->interface);
1237 if (mISDNport->ifport->remote) {
1238 admin = admin_first;
1240 if (admin->remote_name[0] && !strcmp(admin->remote_name, mISDNport->ifport->remote_app))
1242 admin = admin->next;
1245 trace_header("INTERFACE (remote not connected)", DIRECTION_NONE);
1246 add_trace("application", NULL, "%s", mISDNport->ifport->remote_app);
1250 port = new Premote(PORT_TYPE_REMOTE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode, admin->sock);
1252 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);
1254 FATAL("No memory for Port instance\n");
1255 earlyb = mISDNport->earlyb;
1256 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
1257 memset(&dialinginfo, 0, sizeof(dialinginfo));
1258 if (e_dialinginfo.keypad[0])
1259 SCPY(dialinginfo.keypad, number);
1261 SCPY(dialinginfo.id, number);
1262 dialinginfo.itype = INFO_ITYPE_ISDN;
1263 dialinginfo.ntype = e_dialinginfo.ntype;
1264 dialinginfo.sending_complete = e_dialinginfo.sending_complete;
1265 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
1267 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1269 goto check_anycall_extern;
1271 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1272 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1273 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1274 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1275 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1276 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1277 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1278 //terminal if (e_dialinginfo.id)
1279 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1280 /* handle restricted caller ids */
1281 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);
1282 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);
1283 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);
1284 /* display callerid if desired for extension */
1285 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));
1286 message_put(message);
1287 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1291 check_anycall_extern:
1292 /* now we have all ports created */
1294 trace_header("INTERFACE (no free ports found)", DIRECTION_NONE);
1296 if (!ea_endpoint->ep_join_id)
1298 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
1299 return; /* must exit here */
1306 int action_timeout(struct lcr_timer *timer, void *instance, int index)
1308 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1310 if (!ea->e_action || ea->e_state == EPOINT_STATE_CONNECT)
1313 unsched_timer(&ea->e_redial_timeout);
1314 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current action timed out.\n", ea->ea_endpoint->ep_serial);
1315 ea->e_multipoint_cause = 0;
1316 ea->e_multipoint_location = 0;
1317 ea->new_state(EPOINT_STATE_IN_OVERLAP);
1318 ea->e_join_pattern = 0;
1319 ea->process_dialing(1);
1320 /* we must exit, because our endpoint might be gone */
1325 int match_timeout(struct lcr_timer *timer, void *instance, int index)
1327 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1329 if (!ea->e_action) {
1330 unsched_timer(&ea->e_redial_timeout);
1331 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we got a match timeout.\n", ea->ea_endpoint->ep_serial);
1332 ea->process_dialing(0);
1333 /* we must exit, because our endpoint might be gone */
1339 int redial_timeout(struct lcr_timer *timer, void *instance, int index)
1341 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1343 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial.\n", ea->ea_endpoint->ep_serial);
1345 ea->new_state(EPOINT_STATE_OUT_SETUP);
1346 /* call special setup routine */
1352 int powerdial_timeout(struct lcr_timer *timer, void *instance, int index)
1354 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1356 /* leave power dialing on */
1357 ea->e_powerdial_on = 1;
1358 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial of powerdial.\n", ea->ea_endpoint->ep_serial);
1361 ea->e_ruleset = ruleset_main;
1363 ea->e_rule = ea->e_ruleset->rule_first;
1364 ea->e_action = NULL;
1365 ea->new_state(EPOINT_STATE_IN_OVERLAP);
1366 ea->process_dialing(0);
1371 int cfnr_timeout(struct lcr_timer *timer, void *instance, int index)
1373 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1374 struct port_list *portlist;
1375 struct lcr_msg *message;
1377 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-no-response time has expired, hanging up.\n", ea->ea_endpoint->ep_serial);
1379 /* release all ports */
1380 while((portlist = ea->ea_endpoint->ep_portlist)) {
1381 message = message_create(ea->ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1382 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
1383 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1384 message_put(message);
1385 ea->logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1386 ea->ea_endpoint->free_portlist(portlist);
1389 message = message_create(ea->ea_endpoint->ep_serial, ea->ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1390 message->param.audiopath = 0;
1391 message_put(message);
1392 /* indicate no patterns */
1393 message = message_create(ea->ea_endpoint->ep_serial, ea->ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1394 message_put(message);
1395 /* set setup state, since we have no response from the new join */
1396 ea->new_state(EPOINT_STATE_OUT_SETUP);
1401 int cfnr_call_timeout(struct lcr_timer *timer, void *instance, int index)
1403 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1405 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-busy time has expired, calling the forwarded number: %s.\n", ea->ea_endpoint->ep_serial, ea->e_ext.cfnr);
1411 int callback_timeout(struct lcr_timer *timer, void *instance, int index)
1413 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1415 if (ea->e_state == EPOINT_STATE_IDLE) {
1416 /* epoint is idle, check callback */
1417 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting callback.\n", ea->ea_endpoint->ep_serial);
1418 ea->new_state(EPOINT_STATE_OUT_SETUP);
1425 int password_timeout(struct lcr_timer *timer, void *instance, int index)
1427 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1429 if (ea->e_action->index==ACTION_PASSWORD || ea->e_action->index==ACTION_PASSWORD_WRITE) {
1430 struct port_list *portlist;
1432 ea->e_ruleset = ruleset_main;
1434 ea->e_rule = ea->e_ruleset->rule_first;
1435 ea->e_action = NULL;
1436 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) password timeout %s\n", ea->ea_endpoint->ep_serial, ea->e_extdialing);
1437 ea->trace_header("PASSWORD timeout", DIRECTION_NONE);
1439 ea->e_connectedmode = 0;
1441 ea->new_state(EPOINT_STATE_OUT_DISCONNECT);
1442 portlist = ea->ea_endpoint->ep_portlist;
1444 ea->message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
1445 ea->set_tone(portlist, "cause_10");
1452 /* doing a hookflash */
1453 void EndpointAppPBX::hookflash(void)
1458 /* be sure that we are active */
1460 e_tx_state = NOTIFY_STATE_ACTIVE;
1462 trace_header("HOOKFLASH DTMF", DIRECTION_NONE);
1464 if (ea_endpoint->ep_use > 1) {
1465 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot hooflash while child process is running.\n", ea_endpoint->ep_serial);
1468 /* dialtone after pressing the hash key */
1469 process_hangup(e_join_cause, e_join_location);
1470 e_multipoint_cause = 0;
1471 e_multipoint_location = 0;
1472 port = find_port_id(ea_endpoint->ep_portlist->port_id);
1474 port->set_echotest(0);
1476 if (ea_endpoint->ep_join_id) {
1477 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
1479 e_ruleset = ruleset_main;
1481 e_rule = e_ruleset->rule_first;
1483 new_state(EPOINT_STATE_IN_OVERLAP);
1484 e_connectedmode = 1;
1485 SCPY(e_dialinginfo.id, e_ext.prefix);
1486 e_extdialing = e_dialinginfo.id;
1488 if (e_dialinginfo.id[0]) {
1489 set_tone(ea_endpoint->ep_portlist, "dialing");
1492 set_tone(ea_endpoint->ep_portlist, "dialpbx");
1500 /* messages from port
1502 /* port MESSAGE_SETUP */
1503 void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, union parameter *param)
1505 struct lcr_msg *message;
1507 int writeext; /* flags need to write extension after modification */
1509 struct interface *interface;
1511 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1513 portlist->port_type = param->setup.port_type;
1514 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
1515 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
1516 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
1517 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
1519 /* convert (inter-)national number type */
1520 SCPY(e_dialinginfo.id, numberrize_callerinfo(e_dialinginfo.id, e_dialinginfo.ntype, options.national, options.international));
1521 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
1523 // e_dtmf = param->setup.dtmf;
1524 /* screen incoming caller id */
1525 interface = interface_first;
1527 if (!strcmp(e_callerinfo.interface, interface->name)) {
1530 interface = interface->next;
1533 do_screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface);
1534 do_screen(0, e_callerinfo.id2, sizeof(e_callerinfo.id2), &e_callerinfo.ntype2, &e_callerinfo.present2, interface);
1537 /* process extension */
1538 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION) {
1539 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is extension\n", ea_endpoint->ep_serial);
1540 /* port makes call from extension */
1541 SCPY(e_callerinfo.extension, e_callerinfo.id);
1542 SCPY(e_ext.number, e_callerinfo.extension);
1543 SCPY(e_extension_interface, e_callerinfo.interface);
1545 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is external or voip\n", ea_endpoint->ep_serial);
1548 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION) {
1549 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1551 /* get extension's info about caller */
1552 if (!read_extension(&e_ext, e_ext.number)) {
1553 /* extension doesn't exist */
1554 trace_header("EXTENSION (not created)", DIRECTION_IN);
1555 add_trace("extension", NULL, "%s", e_ext.number);
1557 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
1558 new_state(EPOINT_STATE_OUT_DISCONNECT);
1559 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
1560 e_ext.number[0] = '\0'; /* no terminal */
1565 /* put prefix (next) in front of e_dialinginfo.id */
1566 if (e_ext.next[0]) {
1567 SPRINT(buffer, "%s%s", e_ext.next, e_dialinginfo.id);
1568 SCPY(e_dialinginfo.id, buffer);
1569 e_ext.next[0] = '\0';
1571 } else if (e_ext.prefix[0]) {
1572 SPRINT(buffer, "%s%s", e_ext.prefix, e_dialinginfo.id);
1573 SCPY(e_dialinginfo.id, buffer);
1576 /* screen caller id by extension's config */
1577 e_callerinfo.screen = INFO_SCREEN_NETWORK;
1579 SCPY(e_callerinfo.name, e_ext.name);
1580 /* use caller id (or if exist: id_next_call) for this call */
1581 if (e_ext.id_next_call_present >= 0) {
1582 SCPY(e_callerinfo.id, e_ext.id_next_call);
1583 /* if we restrict the pesentation */
1584 if (e_ext.id_next_call_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1585 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1586 else e_callerinfo.present = e_ext.id_next_call_present;
1587 e_callerinfo.ntype = e_ext.id_next_call_type;
1588 e_ext.id_next_call_present = -1;
1591 SCPY(e_callerinfo.id, e_ext.callerid);
1592 /* if we restrict the pesentation */
1593 if (e_ext.callerid_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1594 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1595 else e_callerinfo.present = e_ext.callerid_present;
1596 e_callerinfo.ntype = e_ext.callerid_type;
1598 e_callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
1600 /* extension is written */
1602 write_extension(&e_ext, e_ext.number);
1604 /* set volume of rx and tx */
1605 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1606 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0) {
1607 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
1608 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
1609 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
1610 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
1611 message_put(message);
1614 /* start recording if enabled */
1615 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);
1620 port = find_port_id(portlist->port_id);
1622 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
1626 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from external port\n", ea_endpoint->ep_serial);
1627 /* no terminal identification */
1628 e_ext.number[0] = '\0';
1629 e_extension_interface[0] = '\0';
1630 memset(&e_ext, 0, sizeof(e_ext));
1631 e_ext.rights = 4; /* right to dial internat */
1635 e_ruleset = ruleset_main;
1637 e_rule = e_ruleset->rule_first;
1639 e_extdialing = e_dialinginfo.id;
1640 new_state(EPOINT_STATE_IN_SETUP);
1641 if (e_dialinginfo.id[0]) {
1642 set_tone(portlist, "dialing");
1644 if (e_ext.number[0])
1645 set_tone(portlist, "dialpbx");
1647 set_tone(portlist, "dialtone");
1650 if (e_state == EPOINT_STATE_IN_SETUP) {
1651 /* request MORE info, if not already at higher state */
1652 new_state(EPOINT_STATE_IN_OVERLAP);
1653 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_OVERLAP);
1654 message_put(message);
1655 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1659 /* port MESSAGE_INFORMATION */
1660 void EndpointAppPBX::port_information(struct port_list *portlist, int message_type, union parameter *param)
1662 struct lcr_msg *message;
1664 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1666 /* ignore information message without digit information */
1667 if (!param->information.id[0])
1672 /* turn off dtmf detection, in case dtmf is sent with keypad information */
1674 trace_header("DTMF (disabling due to keypad)", DIRECTION_IN);
1679 /* if vbox_play is done, the information are just used as they come */
1681 if (e_action->index == ACTION_VBOX_PLAY) {
1682 /* concat dialing string */
1683 SCAT(e_dialinginfo.id, param->information.id);
1688 /* keypad when disconnect but in connected mode */
1689 if (e_state==EPOINT_STATE_OUT_DISCONNECT && e_connectedmode) {
1690 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received after disconnect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1691 /* processing keypad function */
1692 if (param->information.id[0] == '0') {
1698 /* keypad when connected */
1699 if (e_state == EPOINT_STATE_CONNECT || e_state == EPOINT_STATE_IN_ALERTING) {
1700 if (e_enablekeypad) {
1701 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1702 memcpy(&message->param, param, sizeof(union parameter));
1703 message_put(message);
1707 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1708 /* processing keypad function */
1709 if (param->information.id[0] == '0') {
1712 if (param->information.id[0])
1713 keypad_function(param->information.id[0]);
1715 if (e_ext.number[0])
1716 trace_header("KEYPAD (not enabled by extension's settings)", DIRECTION_IN);
1718 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1723 if (e_state != EPOINT_STATE_IN_OVERLAP) {
1724 if (e_ext.number[0])
1725 trace_header("KEYPAD (ignored, not connected and not dialing)", DIRECTION_IN);
1727 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1731 if (!param->information.id[0])
1733 if (e_dialinginfo.id[0]=='\0' && !e_action) {
1734 set_tone(portlist, "dialing");
1737 if (e_action->index==ACTION_OUTDIAL
1738 || e_action->index==ACTION_EXTERNAL
1739 || e_action->index==ACTION_REMOTE) {
1741 set_tone(portlist, "dialing");
1742 else if (!e_extdialing[0])
1743 set_tone(portlist, "dialing");
1745 /* concat dialing string */
1746 SCAT(e_dialinginfo.id, param->information.id);
1750 /* port MESSAGE_DTMF */
1751 void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
1754 struct lcr_msg *message;
1758 /* only if dtmf detection is enabled */
1760 trace_header("DTMF (disabled)", DIRECTION_IN);
1764 trace_header("DTMF", DIRECTION_IN);
1765 add_trace("digit", NULL, "%c", param->dtmf);
1769 NOTE: vbox is now handled due to overlap state
1770 /* if vbox_play is done, the dtmf digits are just used as they come */
1772 if (e_action->index == ACTION_VBOX_PLAY) {
1773 /* concat dialing string */
1774 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id)) {
1775 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1776 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1779 /* continue to process *X# sequences */
1783 /* check for *X# sequence */
1784 if (e_state == EPOINT_STATE_CONNECT || e_state == EPOINT_STATE_IN_ALERTING) {
1785 if (e_enablekeypad) {
1786 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1787 memcpy(&message->param, param, sizeof(union parameter));
1788 message_put(message);
1791 if (e_dtmf_time+3 < now) {
1792 /* the last digit was too far in the past to be a sequence */
1793 if (param->dtmf == '*')
1794 /* only start is allowed in the sequence */
1799 /* we have a sequence of digits, see what we got */
1800 if (param->dtmf == '*')
1802 else if (param->dtmf>='0' && param->dtmf<='9') {
1803 /* we need to have a star before we receive the digit of the sequence */
1804 if (e_dtmf_last == '*')
1805 e_dtmf_last = param->dtmf;
1806 } else if (param->dtmf == '#') {
1808 if (e_dtmf_last>='0' && e_dtmf_last<='9') {
1809 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf sequence *%c# detected.\n", ea_endpoint->ep_serial, e_dtmf_last);
1810 if (e_dtmf_last == '0') {
1814 /* processing keypad function */
1816 keypad_function(e_dtmf_last);
1822 /* set last time of dtmf */
1827 /* check for ## hookflash during dialing */
1829 if (e_action->index==ACTION_PASSWORD
1830 || e_action->index==ACTION_PASSWORD_WRITE)
1832 if (param->dtmf=='#') { /* current digit is '#' */
1833 if (e_state==EPOINT_STATE_IN_DISCONNECT
1834 || (e_state!=EPOINT_STATE_CONNECT && e_dtmf_time+3>=now && e_dtmf_last=='#')) { /* when disconnected, just #. when dialing, ##. */
1848 /* dialing using dtmf digit */
1849 if (e_state==EPOINT_STATE_IN_OVERLAP){ // && e_state==e_connectedmode)
1850 if (e_dialinginfo.id[0]=='\0' && !e_action) {
1851 set_tone(portlist, "dialing");
1853 /* concat dialing string */
1854 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id)) {
1855 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1856 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1862 /* port MESSAGE_CRYPT */
1863 void EndpointAppPBX::port_crypt(struct port_list *portlist, int message_type, union parameter *param)
1865 /* send crypt response to cryptman */
1866 if (param->crypt.type == CR_MESSAGE_IND)
1867 cryptman_msg2man(param->crypt.data, param->crypt.len);
1869 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
1872 /* port MESSAGE_OVERLAP */
1873 void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, union parameter *param)
1875 struct lcr_msg *message;
1877 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1879 /* signal to call tool */
1880 admin_call_response(e_adminid, ADMIN_CALL_SETUP_ACK, "", 0, 0, 0);
1882 if (e_dialing_queue[0] && portlist) {
1883 /* send what we have not dialed yet, because we had no setup complete */
1884 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing pending digits: '%s'\n", ea_endpoint->ep_serial, e_dialing_queue);
1885 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
1886 SCPY(message->param.information.id, e_dialing_queue);
1887 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
1888 message_put(message);
1889 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
1890 e_dialing_queue[0] = '\0';
1892 /* check if pattern is available */
1893 if (!ea_endpoint->ep_portlist->next && portlist->early_b) { /* one port_list relation and tones available */
1894 /* indicate patterns */
1895 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1896 message_put(message);
1898 /* connect audio, if not already */
1899 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1900 message->param.audiopath = 1;
1901 message_put(message);
1903 /* indicate no patterns */
1904 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1905 message_put(message);
1907 /* disconnect audio, if not already */
1908 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1909 message->param.audiopath = 0;
1910 message_put(message);
1912 new_state(EPOINT_STATE_OUT_OVERLAP);
1913 /* if we are in a join */
1914 if (ea_endpoint->ep_join_id) {
1915 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1916 memcpy(&message->param, param, sizeof(union parameter));
1917 message_put(message);
1921 /* port MESSAGE_PROCEEDING */
1922 void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_type, union parameter *param)
1924 struct lcr_msg *message;
1926 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1928 /* signal to call tool */
1929 admin_call_response(e_adminid, ADMIN_CALL_PROCEEDING, "", 0, 0, 0);
1931 e_state = EPOINT_STATE_OUT_PROCEEDING;
1932 /* check if pattern is availatle */
1933 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) { /* one port_list relation and tones available */
1934 /* indicate patterns */
1935 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1936 message_put(message);
1938 /* connect audio, if not already */
1939 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1940 message->param.audiopath = 1;
1941 message_put(message);
1943 /* indicate no patterns */
1944 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1945 message_put(message);
1947 /* disconnect audio, if not already */
1948 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1949 message->param.audiopath = 0;
1950 message_put(message);
1952 /* if we are in a call */
1953 if (ea_endpoint->ep_join_id) {
1954 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1955 memcpy(&message->param, param, sizeof(union parameter));
1956 message_put(message);
1960 /* port MESSAGE_ALERTING */
1961 void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type, union parameter *param)
1963 struct lcr_msg *message;
1965 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1967 /* signal to call tool */
1968 admin_call_response(e_adminid, ADMIN_CALL_ALERTING, "", 0, 0, 0);
1971 // set_tone(portlist, "hold");
1973 new_state(EPOINT_STATE_OUT_ALERTING);
1974 /* check if pattern is available */
1975 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) { /* one port_list relation and tones available */
1976 /* indicate patterns */
1977 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1978 message_put(message);
1980 /* connect audio, if not already */
1981 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1982 message->param.audiopath = 1;
1983 message_put(message);
1985 /* indicate no patterns */
1986 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1987 message_put(message);
1989 /* disconnect audio, if not already */
1990 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1991 message->param.audiopath = 0;
1992 message_put(message);
1994 /* if we are in a call */
1995 if (ea_endpoint->ep_join_id) {
1996 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1997 memcpy(&message->param, param, sizeof(union parameter));
1998 message_put(message);
2002 /* port MESSAGE_CONNECT */
2003 void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, union parameter *param)
2005 struct lcr_msg *message;
2007 unsigned int port_id = portlist->port_id;
2008 struct port_list *tportlist;
2010 struct interface *interface;
2013 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2015 /* signal to call tool */
2016 admin_call_response(e_adminid, ADMIN_CALL_CONNECT, numberrize_callerinfo(param->connectinfo.id,param->connectinfo.ntype, options.national, options.international), 0, 0, 0);
2018 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_connectinfo));
2019 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (start)\n", ea_endpoint->ep_serial);
2020 while(ea_endpoint->ep_portlist->next) { /* as long as we have at least two ports */
2021 tportlist = ea_endpoint->ep_portlist;
2022 if (tportlist->port_id == port_id) /* if the first portlist is the calling one, the second must be a different one */
2023 tportlist = tportlist->next;
2024 if (tportlist->port_id == port_id)
2025 FATAL("EPOINT(%d) this should not happen since the portlist list must not have two links to the same port - exitting.\n");
2026 message = message_create(ea_endpoint->ep_serial, tportlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2027 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
2028 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2029 message_put(message);
2030 logmessage(message->type, &message->param, tportlist->port_id, DIRECTION_OUT);
2031 ea_endpoint->free_portlist(tportlist);
2033 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (end)\n", ea_endpoint->ep_serial);
2038 /* screen incoming connected id */
2039 interface = interface_first;
2041 if (!strcmp(e_connectinfo.interface, interface->name)) {
2044 interface = interface->next;
2047 do_screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface);
2049 /* screen connected name */
2051 SCPY(e_connectinfo.name, e_ext.name);
2053 /* add internal id to colp */
2054 SCPY(e_connectinfo.extension, e_ext.number);
2056 /* we store the connected port number */
2057 SCPY(e_extension_interface, e_connectinfo.interface);
2059 /* for internal and am calls, we get the extension's id */
2060 if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE) {
2061 SCPY(e_connectinfo.id, e_ext.callerid);
2062 SCPY(e_connectinfo.extension, e_ext.number);
2063 e_connectinfo.itype = INFO_ITYPE_ISDN_EXTENSION;
2064 e_connectinfo.ntype = e_ext.callerid_type;
2065 e_connectinfo.present = e_ext.callerid_present;
2067 if (portlist->port_type==PORT_TYPE_VBOX_OUT) {
2068 e_connectinfo.itype = INFO_ITYPE_VBOX;
2069 e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2072 new_state(EPOINT_STATE_CONNECT);
2074 /* set volume of rx and tx */
2075 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0) {
2076 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2077 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2078 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
2079 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
2080 message_put(message);
2083 unsched_timer(&e_cfnr_timeout);
2084 unsched_timer(&e_cfnr_call_timeout);
2085 if (e_ext.number[0])
2086 e_dtmf = 1; /* allow dtmf */
2089 /* other calls with no caller id (or not available for the extension) and force colp */
2090 if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE) {
2091 e_connectinfo.ntype = INFO_NTYPE_NOTPRESENT;
2092 if ((portlist->port_type & PORT_CLASS_DIR_MASK) == PORT_CLASS_DIR_OUT) {
2093 /* external extension answered */
2094 port = find_port_id(portlist->port_id);
2096 SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.id, &e_connectinfo.ntype, options.national, options.international));
2097 e_connectinfo.present = INFO_PRESENT_ALLOWED;
2102 /* send connect to join */
2103 if (ea_endpoint->ep_join_id) {
2104 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2105 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
2106 message_put(message);
2108 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2109 message->param.audiopath = 1;
2110 message_put(message);
2111 } else if (!e_adminid) {
2113 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have a callback, so we create a call with cbcaller: \"%s\".\n", ea_endpoint->ep_serial, e_cbcaller);
2114 SCPY(e_ext.number, e_cbcaller);
2115 new_state(EPOINT_STATE_IN_OVERLAP);
2116 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) callback from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2118 /* get extension's info about terminal */
2119 if (!read_extension(&e_ext, e_ext.number)) {
2120 /* extension doesn't exist */
2121 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2122 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
2123 new_state(EPOINT_STATE_OUT_DISCONNECT);
2124 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
2128 /* put prefix in front of e_cbdialing */
2129 SPRINT(buffer, "%s%s", e_ext.prefix, e_cbdialing);
2130 SCPY(e_dialinginfo.id, buffer);
2131 e_dialinginfo.itype = INFO_ITYPE_ISDN;
2132 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
2134 /* use caller id (or if exist: id_next_call) for this call */
2135 e_callerinfo.screen = INFO_SCREEN_NETWORK;
2136 SCPY(e_callerinfo.extension, e_ext.number);
2137 if (e_ext.id_next_call_present >= 0) {
2138 SCPY(e_callerinfo.id, e_ext.id_next_call);
2139 e_callerinfo.present = e_ext.id_next_call_present;
2140 e_callerinfo.ntype = e_ext.id_next_call_type;
2141 e_ext.id_next_call_present = -1;
2142 /* extension is written */
2143 write_extension(&e_ext, e_ext.number);
2145 SCPY(e_callerinfo.id, e_ext.callerid);
2146 e_callerinfo.present = e_ext.callerid_present;
2147 e_callerinfo.ntype = e_ext.callerid_type;
2149 e_callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
2151 e_connectedmode = 1; /* dtmf-hangup & disconnect prevention */
2154 /* check if caller id is NOT authenticated */
2155 if (!parse_callbackauth(e_ext.number, &e_callbackinfo)) {
2156 /* make call state to enter password */
2157 new_state(EPOINT_STATE_IN_OVERLAP);
2158 e_action = &action_password_write;
2159 unsched_timer(&e_match_timeout);
2160 e_match_to_action = NULL;
2161 e_dialinginfo.id[0] = '\0';
2162 e_extdialing = strchr(e_dialinginfo.id, '\0');
2163 schedule_timer(&e_password_timeout, 20, 0);
2166 /* incoming call (callback) */
2167 e_ruleset = ruleset_main;
2169 e_rule = e_ruleset->rule_first;
2171 e_extdialing = e_dialinginfo.id;
2172 if (e_dialinginfo.id[0]) {
2173 set_tone(portlist, "dialing");
2176 set_tone(portlist, "dialpbx");
2179 } else { /* testcall */
2180 set_tone(portlist, "hold");
2183 /* start recording if enabled, not when answering machine answers */
2184 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)) {
2185 /* check if we are a terminal */
2186 if (e_ext.number[0] == '\0')
2187 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
2189 port = find_port_id(portlist->port_id);
2191 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
2196 /* port MESSAGE_DISCONNECT MESSAGE_RELEASE */
2197 void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
2199 struct lcr_msg *message;
2201 unsigned int port_id = portlist->port_id;
2205 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2207 /* signal to call tool */
2208 admin_call_response(e_adminid, (message_type==MESSAGE_DISCONNECT)?ADMIN_CALL_DISCONNECT:ADMIN_CALL_RELEASE, "", param->disconnectinfo.cause, param->disconnectinfo.location, 0);
2210 //#warning does this work? only disconnect when incoming port hat not already disconnected yet?
2211 if (e_state==EPOINT_STATE_IN_DISCONNECT && message_type!=MESSAGE_RELEASE){ // || e_state==EPOINT_STATE_OUT_DISCONNECT || e_state==EPOINT_STATE_IDLE)
2212 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are already disconnected.\n", ea_endpoint->ep_serial);
2217 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);
2218 collect_cause(&e_multipoint_cause, &e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location);
2219 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new multipoint cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location);
2221 /* check if we have more than one portlist relation and we just ignore the disconnect */
2222 if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist->next) {
2223 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the disconnect was from a multipoint call. we just release that relation.\n", ea_endpoint->ep_serial);
2224 portlist = ea_endpoint->ep_portlist;
2226 if (portlist->port_id == port_id)
2228 portlist = portlist->next;
2231 FATAL("EPOINT(%d) no portlist related to the calling port.\n", ea_endpoint->ep_serial);
2232 if (message_type != MESSAGE_RELEASE) {
2233 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2234 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2235 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2236 message_put(message);
2237 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2239 ea_endpoint->free_portlist(portlist);
2240 return; /* one relation removed */
2242 if (e_state == EPOINT_STATE_CONNECT) {
2243 /* use cause from port after connect */
2244 cause = param->disconnectinfo.cause;
2245 location = param->disconnectinfo.location;
2247 /* use multipoint cause if no connect yet */
2248 if (e_multipoint_cause) {
2249 cause = e_multipoint_cause;
2250 location = e_multipoint_location;
2252 cause = CAUSE_NOUSER;
2253 location = LOCATION_PRIVATE_LOCAL;
2257 unsched_timer(&e_cfnr_timeout);
2258 unsched_timer(&e_cfnr_call_timeout);
2260 /* process hangup */
2261 process_hangup(e_join_cause, e_join_location);
2262 e_multipoint_cause = 0;
2263 e_multipoint_location = 0;
2265 if (message_type == MESSAGE_DISCONNECT) {
2266 /* tone to disconnected end */
2267 SPRINT(buffer, "cause_%02x", cause);
2268 if (ea_endpoint->ep_portlist)
2269 set_tone(ea_endpoint->ep_portlist, buffer);
2271 new_state(EPOINT_STATE_IN_DISCONNECT);
2274 if (ea_endpoint->ep_join_id) {
2275 int haspatterns = 0;
2276 /* check if pattern is available */
2277 if (ea_endpoint->ep_portlist)
2278 if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->early_b)
2279 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
2280 && message_type != MESSAGE_RELEASE) // if we release, we are done
2283 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has patterns.\n", ea_endpoint->ep_serial);
2284 /* indicate patterns */
2285 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2286 message_put(message);
2287 /* connect audio, if not already */
2288 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2289 message->param.audiopath = 1;
2290 message_put(message);
2291 /* send disconnect */
2292 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2293 memcpy(&message->param, param, sizeof(union parameter));
2294 message_put(message);
2295 /* disable encryption if disconnected */
2296 //PERROR("REMOVE ME: state =%d, %d\n", e_crypt_state, e_crypt);
2298 cryptman_message(CI_DISCONNECT_IND, NULL, 0);
2301 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
2304 if (message_type == MESSAGE_RELEASE)
2305 ea_endpoint->free_portlist(portlist);
2306 release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, callcause, portcause */
2307 return; /* must exit here */
2310 /* port MESSAGE_TIMEOUT */
2311 void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type, union parameter *param)
2315 trace_header("TIMEOUT", DIRECTION_IN);
2316 message_type = MESSAGE_DISCONNECT;
2317 switch (param->state) {
2318 case PORT_STATE_OUT_SETUP:
2319 case PORT_STATE_OUT_OVERLAP:
2320 add_trace("state", NULL, "outgoing setup/dialing");
2322 /* no user responding */
2323 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2324 return; /* must exit here */
2326 case PORT_STATE_IN_SETUP:
2327 case PORT_STATE_IN_OVERLAP:
2328 add_trace("state", NULL, "incoming setup/dialing");
2329 param->disconnectinfo.cause = CAUSE_INVALID; /* number incomplete */
2330 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2333 case PORT_STATE_OUT_PROCEEDING:
2334 add_trace("state", NULL, "outgoing proceeding");
2336 param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
2337 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2338 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2339 return; /* must exit here */
2341 case PORT_STATE_IN_PROCEEDING:
2342 add_trace("state", NULL, "incoming proceeding");
2343 param->disconnectinfo.cause = CAUSE_NOUSER;
2344 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL; /* no user responding */
2347 case PORT_STATE_OUT_ALERTING:
2348 add_trace("state", NULL, "outgoing alerting");
2350 param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
2351 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2352 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2353 return; /* must exit here */
2355 case PORT_STATE_CONNECT:
2356 add_trace("state", NULL, "connect");
2358 param->disconnectinfo.cause = CAUSE_NORMAL; /* normal */
2359 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2360 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2361 return; /* must exit here */
2363 case PORT_STATE_IN_ALERTING:
2364 add_trace("state", NULL, "incoming alerting");
2365 param->disconnectinfo.cause = CAUSE_NOANSWER;
2366 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2369 case PORT_STATE_IN_DISCONNECT:
2370 case PORT_STATE_OUT_DISCONNECT:
2371 add_trace("state", NULL, "disconnect");
2373 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
2374 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2375 return; /* must exit here */
2378 param->disconnectinfo.cause = 31; /* normal unspecified */
2379 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2382 /* release call, disconnect isdn */
2384 new_state(EPOINT_STATE_OUT_DISCONNECT);
2385 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2386 SCPY(e_tone, cause);
2388 set_tone(portlist, cause);
2389 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2390 portlist = portlist->next;
2392 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
2395 /* port MESSAGE_NOTIFY */
2396 void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, union parameter *param)
2398 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2400 struct lcr_msg *message;
2401 const char *logtext = "";
2404 /* signal to call tool */
2405 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);
2406 if (param->notifyinfo.notify) {
2407 e_rx_state = track_notify(e_rx_state, param->notifyinfo.notify);
2410 /* if we get notification from stack, local shows if we disabled/enabled audio stream */
2411 if (param->notifyinfo.local) switch(param->notifyinfo.notify) {
2412 case INFO_NOTIFY_REMOTE_HOLD:
2413 case INFO_NOTIFY_USER_SUSPENDED:
2414 /* tell call about it */
2415 if (ea_endpoint->ep_join_id) {
2416 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2417 message->param.audiopath = 0;
2418 message_put(message);
2422 case INFO_NOTIFY_REMOTE_RETRIEVAL:
2423 case INFO_NOTIFY_USER_RESUMED:
2424 /* set volume of rx and tx */
2425 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
2426 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
2428 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2429 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2430 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
2431 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
2432 message_put(message);
2434 /* set current tone */
2436 set_tone(portlist, e_tone);
2437 /* tell call about it */
2438 if (ea_endpoint->ep_join_id) {
2439 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2440 message->param.audiopath = 1;
2441 message_put(message);
2446 /* get name of notify */
2447 switch(param->notifyinfo.notify) {
2452 logtext = "USER_SUSPENDED";
2455 logtext = "BEARER_SERVICE_CHANGED";
2458 logtext = "USER_RESUMED";
2461 logtext = "CONFERENCE_ESTABLISHED";
2464 logtext = "CONFERENCE_DISCONNECTED";
2467 logtext = "OTHER_PARTY_ADDED";
2470 logtext = "ISOLATED";
2473 logtext = "REATTACHED";
2476 logtext = "OTHER_PARTY_ISOLATED";
2479 logtext = "OTHER_PARTY_REATTACHED";
2482 logtext = "OTHER_PARTY_SPLIT";
2485 logtext = "OTHER_PARTY_DISCONNECTED";
2488 logtext = "CONFERENCE_FLOATING";
2491 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
2494 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
2497 logtext = "CALL_IS_A_WAITING_CALL";
2500 logtext = "DIVERSION_ACTIVATED";
2503 logtext = "RESERVED_CT_1";
2506 logtext = "RESERVED_CT_2";
2509 logtext = "REVERSE_CHARGING";
2512 logtext = "REMOTE_HOLD";
2515 logtext = "REMOTE_RETRIEVAL";
2518 logtext = "CALL_IS_DIVERTING";
2521 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
2526 /* notify call if available */
2527 if (ea_endpoint->ep_join_id) {
2528 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOTIFY);
2529 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
2530 message_put(message);
2535 /* port MESSAGE_PROGRESS */
2536 void EndpointAppPBX::port_progress(struct port_list *portlist, int message_type, union parameter *param)
2538 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2540 struct lcr_msg *message;
2542 /* signal to call tool */
2543 admin_call_response(e_adminid, ADMIN_CALL_PROGRESS, "", 0, param->progressinfo.location, param->progressinfo.progress);
2545 /* send progress to call if available */
2546 if (ea_endpoint->ep_join_id) {
2547 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PROGRESS);
2548 memcpy(&message->param.progressinfo, ¶m->progressinfo, sizeof(struct progress_info));
2549 message_put(message);
2554 /* port MESSAGE_FACILITY */
2555 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
2557 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2559 struct lcr_msg *message;
2561 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_FACILITY);
2562 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2563 message_put(message);
2566 /* port MESSAGE_SUSPEND */
2567 /* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
2568 void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
2570 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2572 /* epoint is now parked */
2573 ea_endpoint->ep_park = 1;
2574 memcpy(ea_endpoint->ep_park_callid, param->parkinfo.callid, sizeof(ea_endpoint->ep_park_callid));
2575 ea_endpoint->ep_park_len = (param->parkinfo.len>8)?8:param->parkinfo.len;
2577 /* remove port relation */
2578 ea_endpoint->free_portlist(portlist);
2581 /* port MESSAGE_RESUME */
2582 /* NOTE: before resume, the active-notification must be done in order to set call mixer */
2583 void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
2585 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2587 /* epoint is now resumed */
2588 ea_endpoint->ep_park = 0;
2592 /* port MESSAGE_ENABLEKEYPAD */
2593 void EndpointAppPBX::port_enablekeypad(struct port_list *portlist, int message_type, union parameter *param)
2595 struct lcr_msg *message;
2597 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2599 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_ENABLEKEYPAD);
2600 memcpy(&message->param, param, sizeof(union parameter));
2601 message_put(message);
2605 /* port sends message to the endpoint
2607 void EndpointAppPBX::ea_message_port(unsigned int port_id, int message_type, union parameter *param)
2609 struct port_list *portlist;
2611 portlist = ea_endpoint->ep_portlist;
2613 if (port_id == portlist->port_id)
2615 portlist = portlist->next;
2618 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);
2622 // PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
2623 switch(message_type) {
2624 case MESSAGE_DATA: /* data from port */
2625 /* check if there is a call */
2626 if (!ea_endpoint->ep_join_id)
2628 /* continue if only one portlist */
2629 if (ea_endpoint->ep_portlist->next != NULL)
2631 /* forward message */
2632 message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2635 case MESSAGE_TONE_EOF: /* tone is end of file */
2636 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
2638 if (e_action->index == ACTION_VBOX_PLAY) {
2641 if (e_action->index == ACTION_EFI) {
2647 case MESSAGE_TONE_COUNTER: /* counter info received */
2648 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);
2650 if (e_action->index == ACTION_VBOX_PLAY) {
2651 e_vbox_counter = param->counter.current;
2652 if (param->counter.max >= 0)
2653 e_vbox_counter_max = param->counter.max;
2657 /* PORT sends SETUP message */
2659 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);
2660 if (e_state!=EPOINT_STATE_IDLE) {
2661 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
2664 port_setup(portlist, message_type, param);
2667 /* PORT sends INFORMATION message */
2668 case MESSAGE_INFORMATION: /* additional digits received */
2669 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);
2670 port_information(portlist, message_type, param);
2673 /* PORT sends FACILITY message */
2674 case MESSAGE_FACILITY:
2675 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2676 port_facility(portlist, message_type, param);
2679 /* PORT sends DTMF message */
2680 case MESSAGE_DTMF: /* dtmf digits received */
2681 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);
2682 port_dtmf(portlist, message_type, param);
2685 /* PORT sends CRYPT message */
2686 case MESSAGE_CRYPT: /* crypt response received */
2687 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) crypt response=%d\n", ea_endpoint->ep_serial, param->crypt.type);
2688 port_crypt(portlist, message_type, param);
2691 /* PORT sends MORE message */
2692 case MESSAGE_OVERLAP:
2693 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);
2694 if (e_state != EPOINT_STATE_OUT_SETUP) {
2695 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);
2698 port_overlap(portlist, message_type, param);
2701 /* PORT sends PROCEEDING message */
2702 case MESSAGE_PROCEEDING: /* port is proceeding */
2703 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);
2704 if (e_state!=EPOINT_STATE_OUT_SETUP
2705 && e_state!=EPOINT_STATE_OUT_OVERLAP) {
2706 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);
2709 port_proceeding(portlist, message_type, param);
2712 /* PORT sends ALERTING message */
2713 case MESSAGE_ALERTING:
2714 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);
2715 if (e_state!=EPOINT_STATE_OUT_SETUP
2716 && e_state!=EPOINT_STATE_OUT_OVERLAP
2717 && e_state!=EPOINT_STATE_OUT_PROCEEDING) {
2718 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);
2721 port_alerting(portlist, message_type, param);
2724 /* PORT sends CONNECT message */
2725 case MESSAGE_CONNECT:
2726 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);
2727 if (e_state!=EPOINT_STATE_OUT_SETUP
2728 && e_state!=EPOINT_STATE_OUT_OVERLAP
2729 && e_state!=EPOINT_STATE_OUT_PROCEEDING
2730 && e_state!=EPOINT_STATE_OUT_ALERTING) {
2731 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
2734 port_connect(portlist, message_type, param);
2737 /* PORT sends DISCONNECT message */
2738 case MESSAGE_DISCONNECT: /* port is disconnected */
2739 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);
2740 port_disconnect_release(portlist, message_type, param);
2743 /* PORT sends a RELEASE message */
2744 case MESSAGE_RELEASE: /* port releases */
2745 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);
2746 /* portlist is release at port_disconnect_release, thanx Paul */
2747 port_disconnect_release(portlist, message_type, param);
2750 /* PORT sends a TIMEOUT message */
2751 case MESSAGE_TIMEOUT:
2752 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);
2753 port_timeout(portlist, message_type, param);
2754 break; /* release */
2756 /* PORT sends a NOTIFY message */
2757 case MESSAGE_NOTIFY:
2758 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);
2759 port_notify(portlist, message_type, param);
2762 /* PORT sends a PROGRESS message */
2763 case MESSAGE_PROGRESS:
2764 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received progress.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2765 port_progress(portlist, message_type, param);
2768 /* PORT sends a SUSPEND message */
2769 case MESSAGE_SUSPEND:
2770 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);
2771 port_suspend(portlist, message_type, param);
2772 break; /* suspend */
2774 /* PORT sends a RESUME message */
2775 case MESSAGE_RESUME:
2776 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);
2777 port_resume(portlist, message_type, param);
2781 kann nach dem test gelöscht werden, da eine direkte funktion im join und im mISDN zum austausch der message existiert
2782 /* port assigns bchannel */
2783 case MESSAGE_BCHANNEL: /* bchannel assignment messafe */
2784 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);
2785 /* only one port is expected to be connected to bchannel */
2786 message = message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2787 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_IN);
2791 /* PORT requests DTMF */
2792 case MESSAGE_ENABLEKEYPAD:
2793 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') requests DTMF/KEYPAD.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2794 port_enablekeypad(portlist, message_type, param);
2799 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);
2802 /* Note: this endpoint may be destroyed, so we MUST return */
2806 /* messages from join
2808 /* join MESSAGE_CRYPT */
2809 void EndpointAppPBX::join_crypt(struct port_list *portlist, int message_type, union parameter *param)
2811 switch(param->crypt.type) {
2812 /* message from remote port to "crypt manager" */
2813 case CU_ACTK_REQ: /* activate key-exchange */
2814 case CU_ACTS_REQ: /* activate shared key */
2815 case CU_DACT_REQ: /* deactivate */
2816 case CU_INFO_REQ: /* request last info message */
2817 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2820 /* message from "crypt manager" to user */
2821 case CU_ACTK_CONF: /* key-echange done */
2822 case CU_ACTS_CONF: /* shared key done */
2823 case CU_DACT_CONF: /* deactivated */
2824 case CU_DACT_IND: /* deactivated */
2825 case CU_ERROR_IND: /* receive error message */
2826 case CU_INFO_IND: /* receive info message */
2827 case CU_INFO_CONF: /* receive info message */
2828 encrypt_result(param->crypt.type, (char *)param->crypt.data);
2832 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);
2836 /* join MESSAGE_INFORMATION */
2837 void EndpointAppPBX::join_information(struct port_list *portlist, int message_type, union parameter *param)
2839 struct lcr_msg *message;
2844 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2845 memcpy(&message->param.information, ¶m->information, sizeof(struct dialing_info));
2846 message_put(message);
2847 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2848 portlist = portlist->next;
2852 /* join MESSAGE_FACILITY */
2853 void EndpointAppPBX::join_facility(struct port_list *portlist, int message_type, union parameter *param)
2855 struct lcr_msg *message;
2857 if (!e_ext.facility && e_ext.number[0]) {
2862 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_FACILITY);
2863 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2864 message_put(message);
2865 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2866 portlist = portlist->next;
2870 /* join MESSAGE_MORE */
2871 void EndpointAppPBX::join_overlap(struct port_list *portlist, int message_type, union parameter *param)
2873 struct lcr_msg *message;
2875 new_state(EPOINT_STATE_IN_OVERLAP);
2878 if (e_join_pattern && e_ext.own_setup) {
2879 /* disconnect audio */
2880 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2881 message->param.audiopath = 0;
2882 message_put(message);
2884 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL) {
2885 if (e_dialinginfo.id[0])
2886 set_tone(portlist, "dialing");
2888 set_tone(portlist, "dialtone");
2891 if (e_dialinginfo.id[0]) {
2892 set_tone(portlist, "dialing");
2894 if (e_ext.number[0])
2895 set_tone(portlist, "dialpbx");
2897 set_tone(portlist, "dialtone");
2901 /* join MESSAGE_PROCEEDING */
2902 void EndpointAppPBX::join_proceeding(struct port_list *portlist, int message_type, union parameter *param)
2904 struct lcr_msg *message;
2906 new_state(EPOINT_STATE_IN_PROCEEDING);
2908 /* own proceeding tone */
2909 if (e_join_pattern) {
2910 /* connect / disconnect audio */
2911 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2912 if (e_ext.own_proceeding)
2913 message->param.audiopath = 0;
2915 message->param.audiopath = 1;
2916 message_put(message);
2918 // UCPY(e_join_tone, "proceeding");
2920 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
2921 message_put(message);
2922 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2924 set_tone(portlist, "proceeding");
2927 /* join MESSAGE_ALERTING */
2928 void EndpointAppPBX::join_alerting(struct port_list *portlist, int message_type, union parameter *param)
2930 struct lcr_msg *message;
2932 new_state(EPOINT_STATE_IN_ALERTING);
2934 /* own alerting tone */
2935 if (e_join_pattern) {
2936 /* connect / disconnect audio */
2937 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2938 if (e_ext.own_alerting)
2939 message->param.audiopath = 0;
2941 message->param.audiopath = 1;
2942 message_put(message);
2945 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
2946 message_put(message);
2947 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2949 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL) {
2950 set_tone(portlist, "ringing");
2953 if (e_ext.number[0])
2954 set_tone(portlist, "ringpbx");
2956 set_tone(portlist, "ringing");
2958 if (e_ext.number[0])
2959 e_dtmf = 1; /* allow dtmf */
2962 /* join MESSAGE_CONNECT */
2963 void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type, union parameter *param)
2965 struct lcr_msg *message;
2968 new_state(EPOINT_STATE_CONNECT);
2969 // UCPY(e_join_tone, "");
2971 if (e_ext.number[0])
2972 e_dtmf = 1; /* allow dtmf */
2975 unsched_timer(&e_powerdial_timeout);
2976 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_callerinfo));
2978 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
2979 memcpy(&message->param, param, sizeof(union parameter));
2981 /* screen clip if prefix is required */
2982 if (e_ext.number[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0]) {
2983 SCPY(message->param.connectinfo.id, e_ext.clip_prefix);
2984 SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype, options.national, options.international));
2985 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2988 /* use internal caller id */
2989 if (e_ext.number[0] && e_connectinfo.extension[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore)) {
2990 SCPY(message->param.connectinfo.id, e_connectinfo.extension);
2991 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2994 /* handle restricted caller ids */
2995 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);
2996 /* display callerid if desired for extension */
2997 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));
2999 /* use conp, if enabld */
3000 // if (!e_ext.centrex)
3001 // message->param.connectinfo.name[0] = '\0';
3004 message_put(message);
3005 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3007 set_tone(portlist, NULL);
3009 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3010 message->param.audiopath = 1;
3011 message_put(message);
3016 /* join MESSAGE_DISCONNECT MESSAGE_RELEASE */
3017 void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *param)
3020 struct lcr_msg *message;
3021 struct port_list *portlist = NULL;
3025 /* be sure that we are active */
3027 e_tx_state = NOTIFY_STATE_ACTIVE;
3029 /* we are powerdialing, if e_powerdial_on is set and limit is not exceeded if given */
3030 if (e_powerdial_on && ((e_powercount+1)<e_powerlimit || e_powerlimit<1)) {
3031 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL,0 ); /* RELEASE_TYPE, join, port */
3033 /* set time for power dialing */
3034 schedule_timer(&e_powerdial_timeout, (int)e_powerdelay, 0); /* set redial in the future */
3037 /* set redial tone */
3038 if (ea_endpoint->ep_portlist) {
3041 set_tone(ea_endpoint->ep_portlist, "redial");
3042 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);
3043 /* send proceeding when powerdialing and still setup (avoid dialing timeout) */
3044 if (e_state==EPOINT_STATE_IN_OVERLAP) {
3045 new_state(EPOINT_STATE_IN_PROCEEDING);
3046 if (ea_endpoint->ep_portlist) {
3047 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3048 message_put(message);
3049 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3051 /* caused the error, that the first knock sound was not there */
3052 /* set_tone(portlist, "proceeding"); */
3054 /* send display of powerdialing */
3055 if (e_ext.display_dialing) {
3056 portlist = ea_endpoint->ep_portlist;
3058 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3060 SPRINT(message->param.notifyinfo.display, "Retry %d of %d", e_powercount, e_powerlimit);
3062 SPRINT(message->param.notifyinfo.display, "Retry %d", e_powercount);
3063 message_put(message);
3064 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3065 portlist = portlist->next;
3075 if ((e_state!=EPOINT_STATE_CONNECT
3076 && e_state!=EPOINT_STATE_OUT_DISCONNECT
3077 && e_state!=EPOINT_STATE_IN_OVERLAP
3078 && e_state!=EPOINT_STATE_IN_PROCEEDING
3079 && e_state!=EPOINT_STATE_IN_ALERTING)
3080 || !ea_endpoint->ep_portlist) { /* or no port */
3081 process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
3082 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause, 0); /* RELEASE_TYPE, join, port */
3083 return; /* must exit here */
3086 if (!e_join_cause) {
3087 e_join_cause = param->disconnectinfo.cause;
3088 e_join_location = param->disconnectinfo.location;
3091 /* on release we need the audio again! */
3092 if (message_type == MESSAGE_RELEASE) {
3094 ea_endpoint->ep_join_id = 0;
3096 /* disconnect and select tone */
3097 new_state(EPOINT_STATE_OUT_DISCONNECT);
3098 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
3099 /* if own_cause, we must release the join */
3100 if (e_ext.own_cause /* own cause */
3101 || !e_join_pattern) { /* no patterns */
3102 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);
3103 if (message_type != MESSAGE_RELEASE)
3104 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
3106 } else { /* else we enable audio */
3107 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3108 message->param.audiopath = 1;
3109 message_put(message);
3111 /* send disconnect message */
3112 SCPY(e_tone, cause);
3113 portlist = ea_endpoint->ep_portlist;
3115 set_tone(portlist, cause);
3116 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
3117 portlist = portlist->next;
3121 /* join MESSAGE_SETUP */
3122 void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, union parameter *param)
3124 struct lcr_msg *message;
3125 // struct interface *interface;
3127 /* if we already in setup state, we just update the dialing with new digits */
3128 if (e_state == EPOINT_STATE_OUT_SETUP
3129 || e_state == EPOINT_STATE_OUT_OVERLAP) {
3130 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we are in setup state, so we do overlap dialing.\n", ea_endpoint->ep_serial);
3131 /* if digits changed, what we have already dialed */
3132 if (!!strncmp(e_dialinginfo.id,param->setup.dialinginfo.id,strlen(e_dialinginfo.id))) {
3133 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);
3134 /* release all ports */
3135 while((portlist = ea_endpoint->ep_portlist)) {
3136 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
3137 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
3138 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3139 message_put(message);
3140 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3141 ea_endpoint->free_portlist(portlist);
3144 /* disconnect audio */
3145 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3146 message->param.audiopath = 0;
3147 message_put(message);
3149 /* get dialing info */
3150 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3151 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3152 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3153 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3154 new_state(EPOINT_STATE_OUT_OVERLAP);
3157 schedule_timer(&e_redial_timeout, 1, 0);
3160 /* if we have a pending redial, so we just adjust the dialing number */
3161 if (e_redial_timeout.active) {
3162 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);
3163 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3166 if (!ea_endpoint->ep_portlist) {
3167 PERROR("ERROR: overlap dialing to a NULL port relation\n");
3169 if (ea_endpoint->ep_portlist->next) {
3170 PERROR("ERROR: overlap dialing to a port_list port relation\n");
3172 if (e_state == EPOINT_STATE_OUT_SETUP) {
3174 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);
3175 SCAT(e_dialing_queue, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3178 /* get what we have not dialed yet */
3179 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));
3180 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
3181 SCPY(message->param.information.id, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3182 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
3183 message_put(message);
3184 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3186 /* always store what we have dialed or queued */
3187 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3191 if (e_state != EPOINT_STATE_IDLE) {
3192 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
3195 /* if an internal extension is dialed, copy that number */
3196 if (param->setup.dialinginfo.itype==INFO_ITYPE_ISDN_EXTENSION || param->setup.dialinginfo.itype==INFO_ITYPE_VBOX)
3197 SCPY(e_ext.number, param->setup.dialinginfo.id);
3198 /* if an internal extension is dialed, get extension's info about caller */
3199 if (e_ext.number[0]) {
3200 if (!read_extension(&e_ext, e_ext.number)) {
3201 e_ext.number[0] = '\0';
3202 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the called terminal='%s' is not found in directory tree!\n", ea_endpoint->ep_serial, e_ext.number);
3206 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3207 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3208 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3209 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3211 /* process (voice over) data calls */
3212 if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO) {
3213 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) handling data call as audio call: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
3214 memset(&e_capainfo, 0, sizeof(e_capainfo));
3215 e_capainfo.bearer_capa = INFO_BC_AUDIO;
3216 e_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
3217 e_capainfo.bearer_info1 = (options.law=='u')?INFO_INFO1_ULAW:INFO_INFO1_ALAW;
3220 new_state(EPOINT_STATE_OUT_SETUP);
3221 /* call special setup routine */
3225 /* join MESSAGE_mISDNSIGNAL */
3226 void EndpointAppPBX::join_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param)
3228 struct lcr_msg *message;
3231 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
3232 memcpy(&message->param, param, sizeof(union parameter));
3233 message_put(message);
3234 portlist = portlist->next;
3238 /* join MESSAGE_NOTIFY */
3239 void EndpointAppPBX::join_notify(struct port_list *portlist, int message_type, union parameter *param)
3241 struct lcr_msg *message;
3244 if (param->notifyinfo.notify) {
3245 new_state = track_notify(e_tx_state, param->notifyinfo.notify);
3246 // /* if notification was generated locally, we turn hold music on/off */
3247 // if (param->notifyinfo.local)
3248 // 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)
3252 if (new_state!=NOTIFY_STATE_HOLD && new_state!=NOTIFY_STATE_SUSPEND) {
3253 if (!strcmp(e_tone, "hold")) { // don't interrupt other tones
3255 set_tone(portlist, "");
3256 portlist = portlist->next;
3259 portlist = ea_endpoint->ep_portlist;
3264 if (new_state==NOTIFY_STATE_HOLD || new_state==NOTIFY_STATE_SUSPEND) {
3266 set_tone(portlist, "hold");
3267 portlist = portlist->next;
3269 portlist = ea_endpoint->ep_portlist;
3274 /* save new state */
3275 e_tx_state = new_state;
3278 /* notify port(s) about it */
3280 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3281 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
3282 /* handle restricted caller ids */
3283 apply_callerid_restriction(&e_ext, message->param.notifyinfo.id, &message->param.notifyinfo.ntype, &message->param.notifyinfo.present, 0, message->param.notifyinfo.extension, NULL);
3284 /* display callerid if desired for extension */
3285 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));
3286 message_put(message);
3287 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3288 portlist = portlist->next;
3292 /* join MESSAGE_DTMF */
3293 void EndpointAppPBX::join_dtmf(struct port_list *portlist, int message_type, union parameter *param)
3295 struct lcr_msg *message;
3298 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DTMF);
3299 memcpy(&message->param, param, sizeof(union parameter));
3300 message_put(message);
3301 portlist = portlist->next;
3305 /* JOIN sends messages to the endpoint
3307 void EndpointAppPBX::ea_message_join(unsigned int join_id, int message_type, union parameter *param)
3309 struct port_list *portlist;
3310 struct lcr_msg *message;
3313 PERROR("EPOINT(%d) error: JOIN == NULL.\n", ea_endpoint->ep_serial);
3317 portlist = ea_endpoint->ep_portlist;
3319 /* send MESSAGE_DATA to port */
3320 if (message_type == MESSAGE_DATA) {
3321 if (join_id == ea_endpoint->ep_join_id) { // still linked with JOIN
3322 /* skip if no port relation */
3325 /* skip if more than one port relation */
3328 /* forward audio data to port */
3329 message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3334 // 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);
3335 switch(message_type) {
3336 /* JOIN SENDS TONE message */
3338 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);
3339 set_tone(portlist, param->tone.name);
3342 /* JOIN SENDS CRYPT message */
3344 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);
3345 join_crypt(portlist, message_type, param);
3348 /* JOIN sends INFORMATION message */
3349 case MESSAGE_INFORMATION:
3350 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);
3351 join_information(portlist, message_type, param);
3354 /* JOIN sends FACILITY message */
3355 case MESSAGE_FACILITY:
3356 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);
3357 join_facility(portlist, message_type, param);
3360 /* JOIN sends OVERLAP message */
3361 case MESSAGE_OVERLAP:
3362 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);
3363 if (e_state!=EPOINT_STATE_IN_SETUP
3364 && e_state!=EPOINT_STATE_IN_OVERLAP) {
3365 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3368 join_overlap(portlist, message_type, param);
3371 /* JOIN sends PROCEEDING message */
3372 case MESSAGE_PROCEEDING:
3373 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);
3374 if(e_state!=EPOINT_STATE_IN_OVERLAP) {
3375 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3378 join_proceeding(portlist, message_type, param);
3381 /* JOIN sends ALERTING message */
3382 case MESSAGE_ALERTING:
3383 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);
3384 if (e_state!=EPOINT_STATE_IN_OVERLAP
3385 && e_state!=EPOINT_STATE_IN_PROCEEDING) {
3386 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state.\n", ea_endpoint->ep_serial);
3389 join_alerting(portlist, message_type, param);
3392 /* JOIN sends CONNECT message */
3393 case MESSAGE_CONNECT:
3394 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);
3395 if (e_state!=EPOINT_STATE_IN_OVERLAP
3396 && e_state!=EPOINT_STATE_IN_PROCEEDING
3397 && e_state!=EPOINT_STATE_IN_ALERTING) {
3398 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
3401 join_connect(portlist, message_type, param);
3404 /* JOIN sends DISCONNECT/RELEASE message */
3405 case MESSAGE_DISCONNECT: /* JOIN disconnect */
3406 case MESSAGE_RELEASE: /* JOIN releases */
3407 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);
3408 join_disconnect_release(message_type, param);
3411 /* JOIN sends SETUP message */
3413 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);
3414 join_setup(portlist, message_type, param);
3417 /* JOIN sends special mISDNSIGNAL message */
3418 case MESSAGE_mISDNSIGNAL: /* isdn message to port */
3419 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);
3420 join_mISDNsignal(portlist, message_type, param);
3424 kann nach dem test gelöscht werden, da eine direkte funktion im join und im mISDN zum austausch der message existiert
3425 /* JOIN requests bchannel */
3426 case MESSAGE_BCHANNEL: /* indicates the need of own bchannel access */
3427 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);
3428 /* only one port is expected to be connected to bchannel */
3435 set_tone(portlist, NULL);
3436 message = message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3437 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3441 /* JOIN has pattern available */
3442 case MESSAGE_PATTERN: /* indicating pattern available */
3443 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);
3444 if (!e_join_pattern) {
3445 PDEBUG(DEBUG_EPOINT, "-> pattern becomes available\n");
3449 set_tone(portlist, NULL);
3450 portlist = portlist->next;
3452 /* connect our audio tx and rx (blueboxing should be possibe before connect :)*/
3453 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3454 message->param.audiopath = 1;
3455 message_put(message);
3459 /* JOIN has no pattern available */
3460 case MESSAGE_NOPATTERN: /* indicating no pattern available */
3461 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);
3462 if (e_join_pattern) {
3463 PDEBUG(DEBUG_EPOINT, "-> pattern becomes unavailable\n");
3465 /* disconnect our audio tx and rx */
3466 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3467 message->param.audiopath = 0;
3468 message_put(message);
3473 /* JOIN (dunno at the moment) */
3474 case MESSAGE_REMOTE_AUDIO:
3475 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);
3476 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3477 message->param.audiopath = param->channel;
3478 message_put(message);
3482 /* JOIN sends a notify message */
3483 case MESSAGE_NOTIFY:
3484 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);
3485 join_notify(portlist, message_type, param);
3488 /* JOIN wants keypad / dtmf */
3489 case MESSAGE_ENABLEKEYPAD:
3490 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);
3493 trace_header("ENABLE KEYPAD", DIRECTION_NONE);
3497 /* JOIN sends a DTMF message */
3499 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received dtmf.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3500 join_dtmf(portlist, message_type, param);
3504 PDEBUG(DEBUG_EPOINT, "EPOI