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, EAPP_TYPE_PBX)
31 class EndpointAppPBX **apppointer;
34 memset(&e_crypt_handler, 0, sizeof(e_crypt_handler));
35 add_timer(&e_crypt_handler, crypt_handler, this, 0);
37 memset(&e_vbox_refresh, 0, sizeof(e_vbox_refresh));
38 add_timer(&e_vbox_refresh, vbox_refresh, this, 0);
39 memset(&e_action_timeout, 0, sizeof(e_action_timeout));
40 add_timer(&e_action_timeout, action_timeout, this, 0);
41 memset(&e_match_timeout, 0, sizeof(e_match_timeout));
42 add_timer(&e_match_timeout, match_timeout, this, 0);
43 memset(&e_redial_timeout, 0, sizeof(e_redial_timeout));
44 add_timer(&e_redial_timeout, redial_timeout, this, 0);
45 memset(&e_powerdial_timeout, 0, sizeof(e_powerdial_timeout));
46 add_timer(&e_powerdial_timeout, powerdial_timeout, this, 0);
47 memset(&e_cfnr_timeout, 0, sizeof(e_cfnr_timeout));
48 add_timer(&e_cfnr_timeout, cfnr_timeout, this, 0);
49 memset(&e_cfnr_call_timeout, 0, sizeof(e_cfnr_call_timeout));
50 add_timer(&e_cfnr_call_timeout, cfnr_call_timeout, this, 0);
51 memset(&e_callback_timeout, 0, sizeof(e_callback_timeout));
52 add_timer(&e_callback_timeout, callback_timeout, this, 0);
53 memset(&e_password_timeout, 0, sizeof(e_password_timeout));
54 add_timer(&e_password_timeout, password_timeout, this, 0);
57 /* add application to chain */
59 apppointer = &apppbx_first;
61 apppointer = &((*apppointer)->next);
65 memset(&e_ext, 0, sizeof(struct extension));
66 // *************** NOTE: also change value in read_extension() **************
67 e_ext.rights = 4; /* international */
68 e_ext.rx_gain = e_ext.tx_gain = 0;
69 e_state = EPOINT_STATE_IDLE;
70 e_ext.number[0] = '\0';
71 e_extension_interface[0] = '\0';
72 memset(&e_callerinfo, 0, sizeof(struct caller_info));
73 memset(&e_dialinginfo, 0, sizeof(struct dialing_info));
74 memset(&e_connectinfo, 0, sizeof(struct connect_info));
75 memset(&e_redirinfo, 0, sizeof(struct redir_info));
76 memset(&e_capainfo, 0, sizeof(struct capa_info));
77 memset(&e_rtpinfo, 0, sizeof(struct rtp_info));
80 e_ruleset = ruleset_main;
82 e_rule = e_ruleset->rule_first;
85 e_match_to_action = NULL;
87 e_extdialing = e_dialinginfo.id;
91 // e_join_tone[0] = e_hold_tone[0] = '\0';
92 e_join_pattern /*= e_hold_pattern*/ = 0;
94 e_adminid = 0; // will be set, if call was initiated via admin socket
97 e_cbdialing[0] = '\0';
100 memset(&e_callbackinfo, 0, sizeof(struct caller_info));
106 e_multipoint_cause = 0;
107 e_multipoint_location = 0;
108 e_dialing_queue[0] = '\0';
111 e_crypt_state = CM_ST_NULL;
112 e_crypt_keyengine_busy = 0;
113 e_crypt_info[0] = '\0';
117 e_tx_state = NOTIFY_STATE_ACTIVE;
118 e_rx_state = NOTIFY_STATE_ACTIVE;
119 e_join_cause = e_join_location = 0;
120 /*********************************
121 *********************************
122 ********* ATTENTION *************
123 *********************************
124 *********************************/
125 /* if you add new values, that must be initialized, also check if they must
126 * be initialized when doing callback
132 * EpointAppPBX destructor
134 EndpointAppPBX::~EndpointAppPBX(void)
136 class EndpointAppPBX *temp, **tempp;
139 del_timer(&e_crypt_handler);
141 del_timer(&e_vbox_refresh);
142 del_timer(&e_action_timeout);
143 del_timer(&e_match_timeout);
144 del_timer(&e_redial_timeout);
145 del_timer(&e_powerdial_timeout);
146 del_timer(&e_cfnr_timeout);
147 del_timer(&e_cfnr_call_timeout);
148 del_timer(&e_callback_timeout);
149 del_timer(&e_password_timeout);
153 tempp = &apppbx_first;
162 FATAL("Endpoint not in endpoint's list.\n");
169 * trace header for application
171 void EndpointAppPBX::trace_header(const char *name, int direction)
175 char msgtext[sizeof(_trace.name)];
179 /* init trace with given values */
182 numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype, options.national, options.international),
186 ea_endpoint->ep_serial,
193 /* set new endpoint state
195 void EndpointAppPBX::new_state(int state)
198 if (e_state != state) {
199 trace_header("NEW STATE", DIRECTION_NONE);
200 add_trace("state", "old", "%s", state_name[e_state]);
201 add_trace("state", "new", "%s", state_name[state]);
209 /* release join and port (as specified)
211 void EndpointAppPBX::release(int release, int joinlocation, int joincause, int portlocation, int portcause, int force)
213 struct port_list *portlist;
214 struct lcr_msg *message;
217 /* message to test call */
218 admin_call_response(e_adminid, ADMIN_CALL_RELEASE, "", joincause, joinlocation, 0);
220 /* if a release is pending */
221 if (release==RELEASE_JOIN || release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY) {
222 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): do pending release (joincause %d location %d)\n", ea_endpoint->ep_serial, joincause, joinlocation);
223 if (ea_endpoint->ep_join_id) {
224 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_RELEASE);
225 message->param.disconnectinfo.cause = joincause;
226 message->param.disconnectinfo.location = joinlocation;
227 message_put(message);
228 ea_endpoint->ep_join_id = 0;
232 if (release != RELEASE_PORT_JOINONLY) {
234 join_release(e_hold_id, ea_endpoint->ep_serial, 1, joinlocation, joincause);
239 if (release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY) {
240 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release (portcause %d portlocation)\n", ea_endpoint->ep_serial, portcause, portlocation);
241 while((portlist = ea_endpoint->ep_portlist)) {
242 if (portlist->port_id) {
243 SPRINT(cause, "cause_%02x", portcause);
244 set_tone(portlist, cause);
245 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
246 message->param.disconnectinfo.cause = portcause;
247 message->param.disconnectinfo.location = portlocation;
248 message->param.disconnectinfo.force = force; // set, if port should release imediately
249 message_put(message);
250 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
252 ea_endpoint->free_portlist(portlist);
255 /* if callback is enabled, call back with the given caller id */
256 if (e_callback_timeout.active) {
257 /* reset some stuff */
258 new_state(EPOINT_STATE_IDLE);
259 memset(&e_connectinfo, 0, sizeof(struct connect_info));
260 memset(&e_redirinfo, 0, sizeof(struct redir_info));
261 e_start = e_stop = 0;
262 e_ruleset = ruleset_main;
264 e_rule = e_ruleset->rule_first;
266 unsched_timer(&e_action_timeout);
267 unsched_timer(&e_match_timeout);
268 unsched_timer(&e_cfnr_timeout);
269 unsched_timer(&e_cfnr_call_timeout);
270 e_match_to_action = NULL;
272 e_extdialing = e_dialinginfo.id;
278 e_multipoint_cause = 0;
279 e_multipoint_location = 0;
280 e_dialing_queue[0] = '\0';
283 e_crypt_state = CM_ST_NULL;
284 e_crypt_keyengine_busy = 0;
285 e_crypt_info[0] = '\0';
290 e_tx_state = NOTIFY_STATE_ACTIVE;
291 e_rx_state = NOTIFY_STATE_ACTIVE;
292 e_join_cause = e_join_location = 0;
294 /* the caller info of the callback user */
295 memcpy(&e_callbackinfo, &e_callerinfo, sizeof(e_callbackinfo));
296 memset(&e_dialinginfo, 0, sizeof(e_dialinginfo));
297 /* create dialing by callerinfo */
298 if (e_ext.number[0] && e_extension_interface[0]) {
299 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to internal: %s interface %s\n", ea_endpoint->ep_serial, e_ext.number, e_extension_interface);
300 /* create callback to the current terminal */
301 SCPY(e_dialinginfo.id, e_ext.number);
302 SCPY(e_dialinginfo.interfaces, e_extension_interface);
303 e_dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
304 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
307 SCPY(e_dialinginfo.id, e_cbto);
309 /* numberrize caller id and use it to dial to the callback */
310 SCPY(e_dialinginfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype, options.national, options.international));
312 e_dialinginfo.itype = INFO_ITYPE_ISDN;
313 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
314 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to external: %s\n", ea_endpoint->ep_serial, e_dialinginfo.id);
319 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release of epoint itself.\n", ea_endpoint->ep_serial);
320 if (--ea_endpoint->ep_use <= 0) /* when e_lock is 0, the endpoint will be deleted */
321 trigger_work(&ea_endpoint->ep_delete);
327 /* cancel callerid if restricted, unless anon-ignore is enabled at extension or port is of type external (so called police gets caller id :)*/
328 void apply_callerid_restriction(struct extension *ext, char *id, int *ntype, int *present, int *screen, char *extension, char *name)
330 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");
332 /* caller id is not restricted, so we do nothing */
333 if (*present != INFO_PRESENT_RESTRICTED)
336 /* only extensions are restricted */
340 /* if we enabled anonymouse ignore */
341 if (ext->anon_ignore)
344 /* else we remove the caller id */
348 *ntype = INFO_NTYPE_UNKNOWN;
350 // *screen = INFO_SCREEN_USER;
351 // maybe we should not make voip address anonymous
354 // maybe it's no fraud to present extension id
356 // extension[0] = '\0';
361 /* used display message to display callerid as available */
362 char *EndpointAppPBX::apply_callerid_display(const char *id, int itype, int ntype, int present, int screen, const char *extension, const char *name)
364 static char display[81];
367 const char *cid = numberrize_callerinfo(id, ntype, options.national, options.international);
369 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");
378 /* NOTE: is caller is is not available for this extesion, it has been removed by apply_callerid_restriction already */
380 /* internal extension's caller id */
381 if (extension[0] && e_ext.display_int) {
383 SCAT(display, extension);
386 if (itype == INFO_ITYPE_VBOX)
387 SCAT(display, "(vbox)");
389 SCAT(display, "(int)");
392 /* external caller id */
393 if (!extension[0] && e_ext.display_ext) {
396 if (present == INFO_PRESENT_RESTRICTED)
397 SCAT(display, "anonymous");
399 SCAT(display, "unknown");
406 /* display if callerid is anonymouse but available due anon-ignore */
407 if (e_ext.display_anon && present==INFO_PRESENT_RESTRICTED) {
409 SCAT(display, "unknown");
412 SCAT(display, " anon");
415 /* display if callerid is anonymouse but available due anon-ignore */
416 if (e_ext.display_fake && screen==INFO_SCREEN_USER && ntype!=INFO_NTYPE_NOTPRESENT) {
419 if (present == INFO_PRESENT_RESTRICTED)
420 SCAT(display, "anonymous");
422 SCAT(display, "unknown");
427 SCAT(display, " fake");
431 if (name[0] && e_ext.display_name) {
432 if (!display[0] && cid[0])
443 * uses the current state to notify activity
445 void EndpointAppPBX::notify_active(void)
447 struct port_list *portlist = ea_endpoint->ep_portlist;
448 struct lcr_msg *message;
452 case NOTIFY_STATE_ACTIVE:
453 /* we are already active, so we don't do anything */
456 case NOTIFY_STATE_SUSPEND:
457 notify = INFO_NOTIFY_USER_RESUMED;
459 set_tone(portlist, NULL);
460 portlist = portlist->next;
462 portlist = ea_endpoint->ep_portlist;
465 case NOTIFY_STATE_HOLD:
466 notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
468 set_tone(portlist, NULL);
469 portlist = portlist->next;
471 portlist = ea_endpoint->ep_portlist;
474 case NOTIFY_STATE_CONFERENCE:
475 notify = INFO_NOTIFY_CONFERENCE_DISCONNECTED;
477 set_tone(portlist, NULL);
478 portlist = portlist->next;
480 portlist = ea_endpoint->ep_portlist;
484 PERROR("unknown e_tx_state = %d\n", e_tx_state);
489 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
490 message->param.notifyinfo.notify = notify;
491 message_put(message);
492 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
493 portlist = portlist->next;
499 * keypad functions during call. one example to use this is to put a call on hold or start a conference
501 void EndpointAppPBX::keypad_function(char digit)
505 /* we must be in a call, in order to send messages to the call */
506 if (e_ext.number[0] == '\0') {
507 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) IGNORING keypad received not from extension.\n", ea_endpoint->ep_serial);
512 /* join conference */
514 if (ea_endpoint->ep_join_id == 0) {
515 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad received during connect but not during a call.\n", ea_endpoint->ep_serial);
518 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join call with call on hold\n", ea_endpoint->ep_serial);
519 port = find_port_id(ea_endpoint->ep_portlist->port_id);
522 if ((port->p_type & PORT_CLASS_POTS_MASK) == PORT_CLASS_POTS_FXS)
524 else if ((port->p_type & PORT_CLASS_mISDN_MASK) == PORT_CLASS_DSS1)
531 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) shared key encryption selected.\n", ea_endpoint->ep_serial);
535 /* crypt key-exchange */
537 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) key exchange encryption selected.\n", ea_endpoint->ep_serial);
543 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) encryption off selected.\n", ea_endpoint->ep_serial);
549 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) unsupported keypad digit '%c'.\n", ea_endpoint->ep_serial, digit);
554 /* set tone pattern for port */
555 void EndpointAppPBX::set_tone(struct port_list *portlist, const char *tone)
557 struct lcr_msg *message;
562 /* store for suspended processes */
566 if (e_join_pattern /* pattern are provided */
567 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_SETUP)
568 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_OVERLAP)
569 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_IN_PROCEEDING)
570 && !(e_ext.own_alerting && e_state == EPOINT_STATE_IN_ALERTING)
571 && !(e_ext.own_cause && e_state == EPOINT_STATE_IN_DISCONNECT)
572 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_SETUP)
573 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_OVERLAP)
574 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_OUT_PROCEEDING)
575 && !(e_ext.own_alerting && e_state == EPOINT_STATE_OUT_ALERTING)
576 && !(e_ext.own_cause && e_state == EPOINT_STATE_OUT_DISCONNECT)
577 && tone[0] && !!strncmp(tone,"crypt_*",6)) {
578 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) tone not provided since patterns are available\n", ea_endpoint->ep_serial);
583 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_TONE);
584 SCPY(message->param.tone.dir, e_ext.tones_dir);
585 SCPY(message->param.tone.name, tone);
586 message_put(message);
587 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
589 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port to notify tone.\n", ea_endpoint->ep_serial);
595 /* outgoing setup to port(s)
596 * ports will be created and a setup is sent if everything is ok. otherwhise
597 * the endpoint is destroyed.
599 void EndpointAppPBX::out_setup(int cfnr)
601 struct dialing_info dialinginfo;
603 struct port_list *portlist;
604 struct lcr_msg *message;
606 int cause = CAUSE_RESSOURCEUNAVAIL;
609 struct interface *interface;
611 struct mISDNport *mISDNport;
615 class EndpointAppPBX *atemp;
616 // char allowed_ports[256];
618 char ifname[sizeof(e_ext.interfaces)],
622 struct port_settings port_settings;
626 struct admin_list *admin;
628 int mode = B_MODE_TRANSPARENT;
630 /* set bchannel mode */
631 mode = e_capainfo.source_mode;
633 /* create settings for creating port */
634 memset(&port_settings, 0, sizeof(port_settings));
636 SCPY(port_settings.tones_dir, e_ext.tones_dir);
638 SCPY(port_settings.tones_dir, options.tones_dir);
639 port_settings.no_seconds = e_ext.no_seconds;
641 /* 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 */
643 /* check what dialinginfo.itype we got */
644 switch(e_dialinginfo.itype) {
645 /* *********************** call to extension or vbox */
646 case INFO_ITYPE_ISDN_EXTENSION:
647 /* check if we deny incoming calls when we use an extension */
648 if (e_ext.noknocking) {
649 atemp = apppbx_first;
652 if (!strcmp(atemp->e_ext.number, e_ext.number))
657 PERROR("EPOINT(%d) noknocking and currently a call\n", ea_endpoint->ep_serial);
658 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYSPE_ join, port */
659 return; /* must exit here */
662 /* FALL THROUGH !!!! */
663 case INFO_ITYPE_VBOX:
664 /* get dialed extension's info */
665 // SCPY(exten, e_dialinginfo.id);
666 // if (strchr(exten, ','))
667 // *strchr(exten, ',') = '\0';
668 // if (!read_extension(&e_ext, exten))
669 if (!read_extension(&e_ext, e_dialinginfo.id)) {
670 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) extension %s not configured\n", ea_endpoint->ep_serial, e_dialinginfo.id);
671 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
672 return; /* must exit here */
674 e_dialinginfo.sending_complete = 1;
676 if (e_dialinginfo.itype == INFO_ITYPE_VBOX) {
677 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing directly to VBOX\n", ea_endpoint->ep_serial);
682 /* string from unconditional call forward (cfu) */
685 /* present to forwarded party */
686 if (e_ext.anon_ignore && e_callerinfo.id[0]) {
687 e_callerinfo.present = INFO_PRESENT_ALLOWED;
689 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
693 /* string from busy call forward (cfb) */
696 class EndpointAppPBX *checkapp = apppbx_first;
698 if (checkapp != this) { /* any other endpoint except our own */
699 if (!strcmp(checkapp->e_ext.number, e_ext.number)) {
700 /* present to forwarded party */
701 if (e_ext.anon_ignore && e_callerinfo.id[0]) {
702 e_callerinfo.present = INFO_PRESENT_ALLOWED;
704 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
708 checkapp = checkapp->next;
712 /* string from no-response call forward (cfnr) */
715 /* when cfnr is done, out_setup() will setup the call */
717 /* present to forwarded party */
718 if (e_ext.anon_ignore && e_callerinfo.id[0]) {
719 e_callerinfo.present = INFO_PRESENT_ALLOWED;
723 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH)) {
724 schedule_timer(&e_cfnr_timeout, e_ext.cfnr_delay, 0);
725 schedule_timer(&e_cfnr_call_timeout, e_ext.cfnr_delay + 1, 0); /* call one second after release */
726 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);
730 /* call to all internal interfaces */
731 p = e_ext.interfaces;
732 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) generating multiple joins for extension %s to interfaces %s\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
736 while(*p!=',' && *p!='\0')
741 /* search interface */
742 interface = hunt_interface(ifname);
744 trace_header("INTERFACE (not found)", DIRECTION_NONE);
745 add_trace("interface", NULL, "%s", ifname);
749 /* found interface */
750 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
751 if (interface->remote) {
754 if (admin->remote_name[0] && !strcmp(admin->remote_name, interface->remote_app))
759 trace_header("INTERFACE (remote not connected)", DIRECTION_NONE);
760 add_trace("application", NULL, "%s", interface->remote_app);
764 SPRINT(portname, "%s-%d-out", interface->name, 0);
765 port = new Premote(PORT_TYPE_REMOTE_OUT, portname, &port_settings, interface, admin->sock);
766 earlyb = (interface->is_earlyb == IS_YES);
769 if (interface->gsm_bs) {
770 SPRINT(portname, "%s-%d-out", interface->name, 0);
771 port = new Pgsm_bs(PORT_TYPE_GSM_BS_OUT, portname, &port_settings, interface);
772 earlyb = (interface->is_earlyb == IS_YES);
776 if (interface->gsm_ms) {
777 SPRINT(portname, "%s-%d-out", interface->name, 0);
778 port = new Pgsm_ms(PORT_TYPE_GSM_MS_OUT, portname, &port_settings, interface);
779 earlyb = (interface->is_earlyb == IS_YES);
783 if (interface->sip) {
784 SPRINT(portname, "%s-%d-out", interface->name, 0);
785 port = new Psip(PORT_TYPE_SIP_OUT, portname, &port_settings, interface);
786 earlyb = (interface->is_earlyb == IS_YES);
791 /* hunt for mISDNport and create Port */
792 mISDNport = hunt_port(ifname, &channel);
794 trace_header("INTERFACE (busy)", DIRECTION_NONE);
795 add_trace("interface", NULL, "%s", ifname);
800 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
803 port = ss5_hunt_line(mISDNport);
806 #ifdef ISDN_P_FXS_POTS
808 port = new Pfxs(PORT_TYPE_POTS_FXS_OUT, mISDNport, portname, &port_settings, mISDNport->ifport->interface, mode);
811 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, mISDNport->ifport->interface, channel, mISDNport->ifport->channel_force, mode);
812 earlyb = mISDNport->earlyb;
814 trace_header("INTERFACE (has no function)", DIRECTION_NONE);
815 add_trace("interface", NULL, "%s", ifname);
821 FATAL("Failed to create Port instance\n");
822 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
823 memset(&dialinginfo, 0, sizeof(dialinginfo));
824 SCPY(dialinginfo.id, e_dialinginfo.id);
825 dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
826 dialinginfo.ntype = e_dialinginfo.ntype;
827 /* create port_list relation */
828 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
830 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
832 goto check_anycall_intern;
835 if (e_callerinfo.id[0] && e_ext.display_name) {
836 dirname = parse_directory(e_callerinfo.id, e_callerinfo.ntype);
838 SCPY(e_callerinfo.name, dirname);
840 // dss1 = (class Pdss1 *)port;
842 //printf("INTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
843 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
844 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
845 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
846 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
847 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
848 memcpy(&message->param.setup.rtpinfo, &e_rtpinfo, sizeof(struct rtp_info));
849 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
850 //terminal if (e_dialinginfo.id)
851 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
852 /* handle restricted caller ids */
853 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);
854 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);
855 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);
856 /* display callerid if desired for extension */
857 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));
858 //printf("\n\ndisplay = %s\n\n\n",message->param.setup.callerinfo.display);
859 /* use cnip, if enabld */
860 // if (!e_ext.centrex)
861 // message->param.setup.callerinfo.name[0] = '\0';
862 /* screen clip if prefix is required */
863 if (message->param.setup.callerinfo.id[0] && e_ext.clip_prefix[0]) {
864 SCPY(message->param.setup.callerinfo.id, e_ext.clip_prefix);
865 SCAT(message->param.setup.callerinfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype, options.national, options.international));
866 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
868 if (message->param.setup.callerinfo.id2[0] && e_ext.clip_prefix[0]) {
869 SCPY(message->param.setup.callerinfo.id2, e_ext.clip_prefix);
870 SCAT(message->param.setup.callerinfo.id2, numberrize_callerinfo(e_callerinfo.id2,e_callerinfo.ntype2, options.national, options.international));
871 message->param.setup.callerinfo.ntype2 = INFO_NTYPE_UNKNOWN;
873 /* use internal caller id */
874 if (e_callerinfo.extension[0] && (message->param.setup.callerinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore)) {
875 SCPY(message->param.setup.callerinfo.id, e_callerinfo.extension);
876 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
877 message->param.setup.callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
879 message_put(message);
880 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
884 /* string from parallel call forward (cfp) */
887 if (e_ext.anon_ignore && e_callerinfo.id[0]) {
888 e_callerinfo.present = INFO_PRESENT_ALLOWED;
889 e_callerinfo.present2 = INFO_PRESENT_ALLOWED;
893 vbox_only: /* entry point for answering machine only */
894 cfu_only: /* entry point for cfu */
895 cfb_only: /* entry point for cfb */
896 cfnr_only: /* entry point for cfnr */
897 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call extension %s for external destiantion(s) '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
901 /* only if vbox should be dialed, and terminal is given */
902 if (!strcmp(p, "vbox") && e_ext.number[0]) {
903 /* go to the end of p */
906 /* answering vbox call */
907 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) answering machine\n", ea_endpoint->ep_serial);
909 if (!(port = new VBoxPort(PORT_TYPE_VBOX_OUT, &port_settings)))
910 FATAL("No memory for VBOX Port instance\n");
911 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocated port %s\n", ea_endpoint->ep_serial, port->p_name);
912 UCPY(cfp, e_ext.number); /* cfp or any other direct forward/vbox */
915 while(*p!=',' && *p!='\0')
920 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cfp external %s\n", ea_endpoint->ep_serial, cfp);
922 /* hunt for mISDNport and create Port */
923 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
925 /* creating EXTERNAL port*/
926 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
929 port = ss5_hunt_line(mISDNport);
932 #ifdef ISDN_P_FXS_POTS
934 port = new Pfxs(PORT_TYPE_POTS_FXS_OUT, mISDNport, portname, &port_settings, mISDNport->ifport->interface, mode);
937 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, mISDNport->ifport->interface, channel, mISDNport->ifport->channel_force, mode);
939 FATAL("No memory for Port instance\n");
940 earlyb = mISDNport->earlyb;
945 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
946 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
951 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port found or created, which is idle.\n", ea_endpoint->ep_serial);
952 goto check_anycall_intern;
954 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found or created port %s\n", ea_endpoint->ep_serial, port->p_name);
955 memset(&dialinginfo, 0, sizeof(dialinginfo));
956 SCPY(dialinginfo.id, cfp);
957 dialinginfo.itype = INFO_ITYPE_ISDN;
958 dialinginfo.ntype = e_dialinginfo.ntype;
959 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
961 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
963 goto check_anycall_intern;
965 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
966 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
967 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
968 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
969 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
970 /* if clip is hidden */
971 if (e_ext.clip==CLIP_HIDE && port->p_type!=PORT_TYPE_VBOX_OUT) {
972 SCPY(message->param.setup.callerinfo.id, e_ext.callerid);
973 SCPY(message->param.setup.callerinfo.extension, e_ext.number);
974 message->param.setup.callerinfo.ntype = e_ext.callerid_type;
975 message->param.setup.callerinfo.present = e_ext.callerid_present;
976 message->param.setup.callerinfo.ntype = INFO_NTYPE_NOTPRESENT;
978 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
979 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
980 //terminal if (e_dialinginfo.id)
981 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
982 /* handle restricted caller ids */
983 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);
984 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);
985 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);
986 /* display callerid if desired for extension */
987 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));
988 message_put(message);
989 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
993 check_anycall_intern:
994 /* now we have all ports created */
996 trace_header("INTERFACE (no extension's interface)", DIRECTION_NONE);
998 if (!ea_endpoint->ep_join_id)
1000 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
1001 return; /* must exit here */
1005 /* *********************** external call */
1007 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: called='%s' keypad='%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id, e_dialinginfo.keypad);
1008 /* call to extenal interfaces */
1009 if (e_dialinginfo.keypad[0])
1010 number_p = e_dialinginfo.keypad;
1012 number_p = e_dialinginfo.id;
1015 while(*number_p!=',' && *number_p!='\0')
1016 SCCAT(number, *number_p++);
1017 if (*number_p == ',')
1021 ifname_p = e_dialinginfo.interfaces;
1022 if (*ifname_p == '+')
1027 while(*ifname_p!=',' && *ifname_p!='\0')
1028 SCCAT(ifname, *ifname_p++);
1029 if (*ifname_p == ',')
1031 /* found interface name */
1033 /* search interface */
1034 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to number '%s' interface '%s'\n", ea_endpoint->ep_serial, number, ifname[0]?ifname:"any interface");
1035 interface = hunt_interface(ifname[0]?ifname:NULL);
1037 trace_header("INTERFACE (not found)", DIRECTION_NONE);
1038 add_trace("interface", NULL, "%s", ifname);
1042 /* found interface */
1043 if (interface->remote) {
1044 admin = admin_first;
1046 if (admin->remote_name[0] && !strcmp(admin->remote_name, interface->remote_app))
1048 admin = admin->next;
1051 trace_header("INTERFACE (remote not connected)", DIRECTION_NONE);
1052 add_trace("application", NULL, "%s", interface->remote_app);
1056 SPRINT(portname, "%s-%d-out", interface->name, 0);
1057 port = new Premote(PORT_TYPE_REMOTE_OUT, portname, &port_settings, interface, admin->sock);
1058 earlyb = (interface->is_earlyb == IS_YES);
1061 if (interface->gsm_bs) {
1062 SPRINT(portname, "%s-%d-out", interface->name, 0);
1063 port = new Pgsm_bs(PORT_TYPE_GSM_BS_OUT, portname, &port_settings, interface);
1064 earlyb = (interface->is_earlyb == IS_YES);
1068 if (interface->gsm_ms) {
1069 SPRINT(portname, "%s-%d-out", interface->name, 0);
1070 port = new Pgsm_ms(PORT_TYPE_GSM_MS_OUT, portname, &port_settings, interface);
1071 earlyb = (interface->is_earlyb == IS_YES);
1075 if (interface->sip) {
1076 SPRINT(portname, "%s-%d-out", interface->name, 0);
1077 port = new Psip(PORT_TYPE_SIP_OUT, portname, &port_settings, interface);
1078 earlyb = (interface->is_earlyb == IS_YES);
1083 /* hunt for mISDNport and create Port */
1084 mISDNport = hunt_port(ifname[0]?ifname:NULL, &channel);
1086 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1087 add_trace("interface", NULL, "%s", ifname[0]?ifname:"any interface");
1091 /* creating EXTERNAL port*/
1092 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1096 port = ss5_hunt_line(mISDNport);
1099 #ifdef ISDN_P_FXS_POTS
1100 if (mISDNport->pots)
1101 port = new Pfxs(PORT_TYPE_POTS_FXS_OUT, mISDNport, portname, &port_settings, mISDNport->ifport->interface, mode);
1104 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, mISDNport->ifport->interface, channel, mISDNport->ifport->channel_force, mode);
1105 earlyb = mISDNport->earlyb;
1107 trace_header("INTERFACE (has no function)", DIRECTION_NONE);
1108 add_trace("interface", NULL, "%s", ifname);
1114 FATAL("No memory for Port instance\n");
1115 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
1116 memset(&dialinginfo, 0, sizeof(dialinginfo));
1117 if (e_dialinginfo.keypad[0])
1118 SCPY(dialinginfo.keypad, number);
1120 SCPY(dialinginfo.id, number);
1121 dialinginfo.itype = INFO_ITYPE_ISDN;
1122 dialinginfo.ntype = e_dialinginfo.ntype;
1123 dialinginfo.sending_complete = e_dialinginfo.sending_complete;
1124 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
1126 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1130 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1131 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1132 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1133 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1134 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1135 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1136 memcpy(&message->param.setup.rtpinfo, &e_rtpinfo, sizeof(struct rtp_info));
1137 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1138 //terminal if (e_dialinginfo.id)
1139 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1140 /* handle restricted caller ids */
1141 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);
1142 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);
1143 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);
1144 /* display callerid if desired for extension */
1145 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));
1146 message_put(message);
1147 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1150 /* found an interface
1151 * continue only if + is given, so every interface is calles parallel */
1152 if (e_dialinginfo.interfaces[0] != '+')
1154 } while (*ifname_p);
1157 /* now we have all ports created */
1159 trace_header("INTERFACE (no free ports found)", DIRECTION_NONE);
1161 if (!ea_endpoint->ep_join_id)
1163 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
1164 return; /* must exit here */
1171 int action_timeout(struct lcr_timer *timer, void *instance, int index)
1173 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1175 if (!ea->e_action || ea->e_state == EPOINT_STATE_CONNECT)
1178 unsched_timer(&ea->e_redial_timeout);
1179 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current action timed out.\n", ea->ea_endpoint->ep_serial);
1180 ea->e_multipoint_cause = 0;
1181 ea->e_multipoint_location = 0;
1182 ea->new_state(EPOINT_STATE_IN_OVERLAP);
1183 ea->e_join_pattern = 0;
1184 ea->process_dialing(1);
1185 /* we must exit, because our endpoint might be gone */
1190 int match_timeout(struct lcr_timer *timer, void *instance, int index)
1192 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1194 if (!ea->e_action) {
1195 unsched_timer(&ea->e_redial_timeout);
1196 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we got a match timeout.\n", ea->ea_endpoint->ep_serial);
1197 ea->process_dialing(0);
1198 /* we must exit, because our endpoint might be gone */
1204 int redial_timeout(struct lcr_timer *timer, void *instance, int index)
1206 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1208 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial.\n", ea->ea_endpoint->ep_serial);
1210 ea->new_state(EPOINT_STATE_OUT_SETUP);
1211 /* call special setup routine */
1217 int powerdial_timeout(struct lcr_timer *timer, void *instance, int index)
1219 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1221 /* leave power dialing on */
1222 ea->e_powerdial_on = 1;
1223 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial of powerdial.\n", ea->ea_endpoint->ep_serial);
1226 ea->e_ruleset = ruleset_main;
1228 ea->e_rule = ea->e_ruleset->rule_first;
1229 ea->e_action = NULL;
1230 ea->new_state(EPOINT_STATE_IN_OVERLAP);
1231 ea->process_dialing(0);
1236 int cfnr_timeout(struct lcr_timer *timer, void *instance, int index)
1238 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1239 struct port_list *portlist;
1240 struct lcr_msg *message;
1242 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-no-response time has expired, hanging up.\n", ea->ea_endpoint->ep_serial);
1244 /* release all ports */
1245 while((portlist = ea->ea_endpoint->ep_portlist)) {
1246 message = message_create(ea->ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1247 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
1248 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1249 message_put(message);
1250 ea->logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1251 ea->ea_endpoint->free_portlist(portlist);
1254 message = message_create(ea->ea_endpoint->ep_serial, ea->ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1255 message->param.audiopath = 0;
1256 message_put(message);
1257 /* indicate no patterns */
1258 message = message_create(ea->ea_endpoint->ep_serial, ea->ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1259 message_put(message);
1260 /* set setup state, since we have no response from the new join */
1261 ea->new_state(EPOINT_STATE_OUT_SETUP);
1266 int cfnr_call_timeout(struct lcr_timer *timer, void *instance, int index)
1268 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1270 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);
1276 int callback_timeout(struct lcr_timer *timer, void *instance, int index)
1278 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1280 if (ea->e_state == EPOINT_STATE_IDLE) {
1281 /* epoint is idle, check callback */
1282 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting callback.\n", ea->ea_endpoint->ep_serial);
1283 ea->new_state(EPOINT_STATE_OUT_SETUP);
1290 int password_timeout(struct lcr_timer *timer, void *instance, int index)
1292 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1294 if (ea->e_action->index==ACTION_PASSWORD || ea->e_action->index==ACTION_PASSWORD_WRITE) {
1295 struct port_list *portlist;
1297 ea->e_ruleset = ruleset_main;
1299 ea->e_rule = ea->e_ruleset->rule_first;
1300 ea->e_action = NULL;
1301 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) password timeout %s\n", ea->ea_endpoint->ep_serial, ea->e_extdialing);
1302 ea->trace_header("PASSWORD timeout", DIRECTION_NONE);
1304 ea->e_connectedmode = 0;
1306 ea->new_state(EPOINT_STATE_OUT_DISCONNECT);
1307 portlist = ea->ea_endpoint->ep_portlist;
1309 ea->message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
1310 ea->set_tone(portlist, "cause_10");
1317 /* doing a hookflash */
1318 void EndpointAppPBX::hookflash(void)
1323 /* be sure that we are active */
1325 e_tx_state = NOTIFY_STATE_ACTIVE;
1327 trace_header("HOOKFLASH DTMF", DIRECTION_NONE);
1329 if (ea_endpoint->ep_use > 1) {
1330 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot hooflash while child process is running.\n", ea_endpoint->ep_serial);
1333 /* dialtone after pressing the hash key */
1334 process_hangup(e_join_cause, e_join_location);
1335 e_multipoint_cause = 0;
1336 e_multipoint_location = 0;
1337 port = find_port_id(ea_endpoint->ep_portlist->port_id);
1339 port->set_echotest(0);
1341 if (ea_endpoint->ep_join_id) {
1342 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
1344 e_ruleset = ruleset_main;
1346 e_rule = e_ruleset->rule_first;
1348 new_state(EPOINT_STATE_IN_OVERLAP);
1349 e_connectedmode = 1;
1350 SCPY(e_dialinginfo.id, e_ext.prefix);
1351 e_extdialing = e_dialinginfo.id;
1353 if (e_dialinginfo.id[0]) {
1354 set_tone(ea_endpoint->ep_portlist, "dialing");
1357 set_tone(ea_endpoint->ep_portlist, "dialpbx");
1365 /* messages from port
1367 /* port MESSAGE_SETUP */
1368 void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, union parameter *param)
1370 struct lcr_msg *message;
1372 int writeext; /* flags need to write extension after modification */
1375 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1377 portlist->port_type = param->setup.port_type;
1378 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
1379 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
1380 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
1381 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
1382 memcpy(&e_rtpinfo, ¶m->setup.rtpinfo, sizeof(e_rtpinfo));
1384 /* convert (inter-)national number type */
1385 SCPY(e_dialinginfo.id, numberrize_callerinfo(e_dialinginfo.id, e_dialinginfo.ntype, options.national, options.international));
1386 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
1388 // e_dtmf = param->setup.dtmf;
1389 /* screen incoming caller id */
1390 if (e_callerinfo.interface[0]) {
1391 do_screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, e_callerinfo.interface);
1392 do_screen(0, e_callerinfo.id2, sizeof(e_callerinfo.id2), &e_callerinfo.ntype2, &e_callerinfo.present2, e_callerinfo.interface);
1393 do_screen(0, e_redirinfo.id, sizeof(e_redirinfo.id), &e_redirinfo.ntype, &e_redirinfo.present, e_callerinfo.interface);
1396 /* process extension */
1397 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION) {
1398 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is extension\n", ea_endpoint->ep_serial);
1399 /* port makes call from extension */
1400 SCPY(e_callerinfo.extension, e_callerinfo.id);
1401 SCPY(e_ext.number, e_callerinfo.extension);
1402 SCPY(e_extension_interface, e_callerinfo.interface);
1404 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is external or voip\n", ea_endpoint->ep_serial);
1407 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION) {
1408 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1410 /* get extension's info about caller */
1411 if (!read_extension(&e_ext, e_ext.number)) {
1412 /* extension doesn't exist */
1413 trace_header("EXTENSION (not created)", DIRECTION_IN);
1414 add_trace("extension", NULL, "%s", e_ext.number);
1416 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
1417 new_state(EPOINT_STATE_OUT_DISCONNECT);
1418 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
1419 e_ext.number[0] = '\0'; /* no terminal */
1424 /* put prefix (next) in front of e_dialinginfo.id */
1425 if (e_ext.next[0]) {
1426 SPRINT(buffer, "%s%s", e_ext.next, e_dialinginfo.id);
1427 SCPY(e_dialinginfo.id, buffer);
1428 e_ext.next[0] = '\0';
1430 } else if (e_ext.prefix[0]) {
1431 SPRINT(buffer, "%s%s", e_ext.prefix, e_dialinginfo.id);
1432 SCPY(e_dialinginfo.id, buffer);
1435 /* screen caller id by extension's config */
1436 e_callerinfo.screen = INFO_SCREEN_NETWORK;
1438 SCPY(e_callerinfo.name, e_ext.name);
1439 /* use caller id (or if exist: id_next_call) for this call */
1440 if (e_ext.id_next_call_present >= 0) {
1441 SCPY(e_callerinfo.id, e_ext.id_next_call);
1442 /* if we restrict the pesentation */
1443 if (e_ext.id_next_call_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1444 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1445 else e_callerinfo.present = e_ext.id_next_call_present;
1446 e_callerinfo.ntype = e_ext.id_next_call_type;
1447 e_ext.id_next_call_present = -1;
1450 SCPY(e_callerinfo.id, e_ext.callerid);
1451 /* if we restrict the pesentation */
1452 if (e_ext.callerid_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1453 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1454 else e_callerinfo.present = e_ext.callerid_present;
1455 e_callerinfo.ntype = e_ext.callerid_type;
1457 e_callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
1459 /* extension is written */
1461 write_extension(&e_ext, e_ext.number);
1463 /* set volume of rx and tx */
1464 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1465 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0) {
1466 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
1467 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
1468 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
1469 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
1470 message_put(message);
1473 /* start recording if enabled */
1474 if (e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO)) {
1475 /* check if we are a terminal */
1476 if (e_ext.number[0] == '\0')
1477 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
1479 port = find_port_id(portlist->port_id);
1481 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
1485 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from external port\n", ea_endpoint->ep_serial);
1486 /* no terminal identification */
1487 e_ext.number[0] = '\0';
1488 e_extension_interface[0] = '\0';
1489 memset(&e_ext, 0, sizeof(e_ext));
1490 e_ext.rights = 4; /* right to dial internat */
1494 e_ruleset = ruleset_main;
1496 e_rule = e_ruleset->rule_first;
1498 e_extdialing = e_dialinginfo.id;
1499 new_state(EPOINT_STATE_IN_SETUP);
1500 if (e_dialinginfo.id[0]) {
1501 set_tone(portlist, "dialing");
1503 if (e_ext.number[0])
1504 set_tone(portlist, "dialpbx");
1506 set_tone(portlist, "dialtone");
1509 if (e_state == EPOINT_STATE_IN_SETUP) {
1510 /* request MORE info, if not already at higher state */
1511 new_state(EPOINT_STATE_IN_OVERLAP);
1512 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_OVERLAP);
1513 message_put(message);
1514 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1518 /* port MESSAGE_INFORMATION */
1519 void EndpointAppPBX::port_information(struct port_list *portlist, int message_type, union parameter *param)
1521 struct lcr_msg *message;
1523 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1525 /* ignore information message without digit information */
1526 if (!param->information.id[0])
1531 /* turn off dtmf detection, in case dtmf is sent with keypad information */
1533 trace_header("DTMF (disabling due to keypad)", DIRECTION_IN);
1538 /* if vbox_play is done, the information are just used as they come */
1540 if (e_action->index == ACTION_VBOX_PLAY) {
1541 /* concat dialing string */
1542 SCAT(e_dialinginfo.id, param->information.id);
1547 /* keypad when disconnect but in connected mode */
1548 if (e_state==EPOINT_STATE_OUT_DISCONNECT && e_connectedmode) {
1549 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received after disconnect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1550 /* processing keypad function */
1551 if (param->information.id[0] == '0') {
1557 /* keypad when connected */
1558 if (e_state == EPOINT_STATE_CONNECT || e_state == EPOINT_STATE_IN_ALERTING) {
1559 if (e_enablekeypad) {
1560 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1561 memcpy(&message->param, param, sizeof(union parameter));
1562 message_put(message);
1566 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1567 /* processing keypad function */
1568 if (param->information.id[0] == '0') {
1571 if (param->information.id[0])
1572 keypad_function(param->information.id[0]);
1574 if (e_ext.number[0])
1575 trace_header("KEYPAD (not enabled by extension's settings)", DIRECTION_IN);
1577 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1582 if (e_state != EPOINT_STATE_IN_OVERLAP) {
1583 if (e_ext.number[0])
1584 trace_header("KEYPAD (ignored, not connected and not dialing)", DIRECTION_IN);
1586 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1590 if (!param->information.id[0])
1592 if (e_dialinginfo.id[0]=='\0' && !e_action) {
1593 set_tone(portlist, "dialing");
1596 if (e_action->index==ACTION_OUTDIAL
1597 || e_action->index==ACTION_EXTERNAL) {
1599 set_tone(portlist, "dialing");
1600 else if (!e_extdialing[0])
1601 set_tone(portlist, "dialing");
1603 /* concat dialing string */
1604 SCAT(e_dialinginfo.id, param->information.id);
1608 /* port MESSAGE_DTMF */
1609 void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
1612 struct lcr_msg *message;
1616 /* only if dtmf detection is enabled */
1618 trace_header("DTMF (disabled)", DIRECTION_IN);
1622 trace_header("DTMF", DIRECTION_IN);
1623 add_trace("digit", NULL, "%c", param->dtmf);
1627 NOTE: vbox is now handled due to overlap state
1628 /* if vbox_play is done, the dtmf digits are just used as they come */
1630 if (e_action->index == ACTION_VBOX_PLAY) {
1631 /* concat dialing string */
1632 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id)) {
1633 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1634 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1637 /* continue to process *X# sequences */
1641 /* check for *X# sequence */
1642 if (e_state == EPOINT_STATE_CONNECT || e_state == EPOINT_STATE_IN_ALERTING) {
1643 if (e_enablekeypad) {
1644 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1645 memcpy(&message->param, param, sizeof(union parameter));
1646 message_put(message);
1649 if (e_dtmf_time+3 < now) {
1650 /* the last digit was too far in the past to be a sequence */
1651 if (param->dtmf == '*')
1652 /* only start is allowed in the sequence */
1657 /* we have a sequence of digits, see what we got */
1658 if (param->dtmf == '*')
1660 else if (param->dtmf>='0' && param->dtmf<='9') {
1661 /* we need to have a star before we receive the digit of the sequence */
1662 if (e_dtmf_last == '*')
1663 e_dtmf_last = param->dtmf;
1664 } else if (param->dtmf == '#') {
1666 if (e_dtmf_last>='0' && e_dtmf_last<='9') {
1667 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf sequence *%c# detected.\n", ea_endpoint->ep_serial, e_dtmf_last);
1668 if (e_dtmf_last == '0') {
1672 /* processing keypad function */
1674 keypad_function(e_dtmf_last);
1680 /* set last time of dtmf */
1685 /* check for ## hookflash during dialing */
1687 if (e_action->index==ACTION_PASSWORD
1688 || e_action->index==ACTION_PASSWORD_WRITE)
1690 if (param->dtmf=='#') { /* current digit is '#' */
1691 if (e_state==EPOINT_STATE_IN_DISCONNECT
1692 || (e_state!=EPOINT_STATE_CONNECT && e_dtmf_time+3>=now && e_dtmf_last=='#')) { /* when disconnected, just #. when dialing, ##. */
1706 /* dialing using dtmf digit */
1707 if (e_state==EPOINT_STATE_IN_OVERLAP){ // && e_state==e_connectedmode)
1708 if (e_dialinginfo.id[0]=='\0' && !e_action) {
1709 set_tone(portlist, "dialing");
1711 /* concat dialing string */
1712 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id)) {
1713 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1714 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1720 /* port MESSAGE_CRYPT */
1721 void EndpointAppPBX::port_crypt(struct port_list *portlist, int message_type, union parameter *param)
1724 /* send crypt response to cryptman */
1725 if (param->crypt.type == CR_MESSAGE_IND)
1726 cryptman_msg2man(param->crypt.data, param->crypt.len);
1728 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
1732 /* port MESSAGE_OVERLAP */
1733 void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, union parameter *param)
1735 struct lcr_msg *message;
1737 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1739 /* signal to call tool */
1740 admin_call_response(e_adminid, ADMIN_CALL_SETUP_ACK, "", 0, 0, 0);
1742 if (e_dialing_queue[0] && portlist) {
1743 /* send what we have not dialed yet, because we had no setup complete */
1744 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing pending digits: '%s'\n", ea_endpoint->ep_serial, e_dialing_queue);
1745 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
1746 SCPY(message->param.information.id, e_dialing_queue);
1747 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
1748 message_put(message);
1749 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
1750 e_dialing_queue[0] = '\0';
1752 /* check if pattern is available */
1753 if (!ea_endpoint->ep_portlist->next && portlist->early_b) { /* one port_list relation and tones available */
1754 /* indicate patterns */
1755 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1756 message_put(message);
1758 /* connect audio, if not already */
1759 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1760 message->param.audiopath = 1;
1761 message_put(message);
1763 /* indicate no patterns */
1764 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1765 message_put(message);
1767 /* disconnect audio, if not already */
1768 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1769 message->param.audiopath = 0;
1770 message_put(message);
1772 new_state(EPOINT_STATE_OUT_OVERLAP);
1773 /* if we are in a join */
1774 if (ea_endpoint->ep_join_id) {
1775 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1776 memcpy(&message->param, param, sizeof(union parameter));
1777 message_put(message);
1781 /* port MESSAGE_PROCEEDING */
1782 void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_type, union parameter *param)
1784 struct lcr_msg *message;
1786 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1788 /* signal to call tool */
1789 admin_call_response(e_adminid, ADMIN_CALL_PROCEEDING, "", 0, 0, 0);
1791 e_state = EPOINT_STATE_OUT_PROCEEDING;
1792 /* check if pattern is availatle */
1793 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) { /* one port_list relation and tones available */
1794 /* indicate patterns */
1795 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1796 message_put(message);
1798 /* connect audio, if not already */
1799 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1800 message->param.audiopath = 1;
1801 message_put(message);
1803 /* indicate no patterns */
1804 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1805 message_put(message);
1807 /* disconnect audio, if not already */
1808 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1809 message->param.audiopath = 0;
1810 message_put(message);
1812 /* if we are in a call */
1813 if (ea_endpoint->ep_join_id) {
1814 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1815 memcpy(&message->param, param, sizeof(union parameter));
1816 message_put(message);
1820 /* port MESSAGE_ALERTING */
1821 void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type, union parameter *param)
1823 struct lcr_msg *message;
1825 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1827 /* signal to call tool */
1828 admin_call_response(e_adminid, ADMIN_CALL_ALERTING, "", 0, 0, 0);
1831 // set_tone(portlist, "hold");
1833 new_state(EPOINT_STATE_OUT_ALERTING);
1834 /* check if pattern is available */
1835 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) { /* one port_list relation and tones available */
1836 /* indicate patterns */
1837 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1838 message_put(message);
1840 /* connect audio, if not already */
1841 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1842 message->param.audiopath = 1;
1843 message_put(message);
1845 /* indicate no patterns */
1846 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1847 message_put(message);
1849 /* disconnect audio, if not already */
1850 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1851 message->param.audiopath = 0;
1852 message_put(message);
1854 /* if we are in a call */
1855 if (ea_endpoint->ep_join_id) {
1856 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1857 memcpy(&message->param, param, sizeof(union parameter));
1858 message_put(message);
1862 /* port MESSAGE_CONNECT */
1863 void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, union parameter *param)
1865 struct lcr_msg *message;
1867 unsigned int port_id = portlist->port_id;
1868 struct port_list *tportlist;
1872 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1874 /* signal to call tool */
1875 admin_call_response(e_adminid, ADMIN_CALL_CONNECT, numberrize_callerinfo(param->connectinfo.id,param->connectinfo.ntype, options.national, options.international), 0, 0, 0);
1877 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_connectinfo));
1878 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (start)\n", ea_endpoint->ep_serial);
1879 while(ea_endpoint->ep_portlist->next) { /* as long as we have at least two ports */
1880 tportlist = ea_endpoint->ep_portlist;
1881 if (tportlist->port_id == port_id) /* if the first portlist is the calling one, the second must be a different one */
1882 tportlist = tportlist->next;
1883 if (tportlist->port_id == port_id)
1884 FATAL("EPOINT(%d) this should not happen since the portlist list must not have two links to the same port - exitting.\n");
1885 message = message_create(ea_endpoint->ep_serial, tportlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1886 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
1887 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1888 message_put(message);
1889 logmessage(message->type, &message->param, tportlist->port_id, DIRECTION_OUT);
1890 ea_endpoint->free_portlist(tportlist);
1892 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (end)\n", ea_endpoint->ep_serial);
1897 if (e_callerinfo.interface[0])
1898 do_screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, e_connectinfo.interface);
1900 /* screen connected name */
1902 SCPY(e_connectinfo.name, e_ext.name);
1904 /* add internal id to colp */
1905 SCPY(e_connectinfo.extension, e_ext.number);
1907 /* we store the connected port number */
1908 SCPY(e_extension_interface, e_connectinfo.interface);
1910 /* for internal and am calls, we get the extension's id */
1911 if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE) {
1912 SCPY(e_connectinfo.id, e_ext.callerid);
1913 SCPY(e_connectinfo.extension, e_ext.number);
1914 e_connectinfo.itype = INFO_ITYPE_ISDN_EXTENSION;
1915 e_connectinfo.ntype = e_ext.callerid_type;
1916 e_connectinfo.present = e_ext.callerid_present;
1918 if (portlist->port_type==PORT_TYPE_VBOX_OUT) {
1919 e_connectinfo.itype = INFO_ITYPE_VBOX;
1920 e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
1923 new_state(EPOINT_STATE_CONNECT);
1925 /* set volume of rx and tx */
1926 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0) {
1927 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
1928 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
1929 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
1930 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
1931 message_put(message);
1934 unsched_timer(&e_cfnr_timeout);
1935 unsched_timer(&e_cfnr_call_timeout);
1936 if (e_ext.number[0])
1937 e_dtmf = 1; /* allow dtmf */
1940 /* other calls with no caller id (or not available for the extension) and force colp */
1941 if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE) {
1942 e_connectinfo.ntype = INFO_NTYPE_NOTPRESENT;
1943 if ((portlist->port_type & PORT_CLASS_DIR_MASK) == PORT_CLASS_DIR_OUT) {
1944 /* external extension answered */
1945 port = find_port_id(portlist->port_id);
1947 SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.id, &e_connectinfo.ntype, options.national, options.international));
1948 e_connectinfo.present = INFO_PRESENT_ALLOWED;
1953 /* send connect to join */
1954 if (ea_endpoint->ep_join_id) {
1955 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1956 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
1957 message_put(message);
1959 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1960 message->param.audiopath = 1;
1961 message_put(message);
1962 } else if (!e_adminid) {
1964 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have a callback, so we create a call with cbcaller: \"%s\".\n", ea_endpoint->ep_serial, e_cbcaller);
1965 SCPY(e_ext.number, e_cbcaller);
1966 new_state(EPOINT_STATE_IN_OVERLAP);
1967 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) callback from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1969 /* get extension's info about terminal */
1970 if (!read_extension(&e_ext, e_ext.number)) {
1971 /* extension doesn't exist */
1972 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1973 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
1974 new_state(EPOINT_STATE_OUT_DISCONNECT);
1975 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
1979 /* put prefix in front of e_cbdialing */
1980 SPRINT(buffer, "%s%s", e_ext.prefix, e_cbdialing);
1981 SCPY(e_dialinginfo.id, buffer);
1982 e_dialinginfo.itype = INFO_ITYPE_ISDN;
1983 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
1985 /* use caller id (or if exist: id_next_call) for this call */
1986 e_callerinfo.screen = INFO_SCREEN_NETWORK;
1987 SCPY(e_callerinfo.extension, e_ext.number);
1988 if (e_ext.id_next_call_present >= 0) {
1989 SCPY(e_callerinfo.id, e_ext.id_next_call);
1990 e_callerinfo.present = e_ext.id_next_call_present;
1991 e_callerinfo.ntype = e_ext.id_next_call_type;
1992 e_ext.id_next_call_present = -1;
1993 /* extension is written */
1994 write_extension(&e_ext, e_ext.number);
1996 SCPY(e_callerinfo.id, e_ext.callerid);
1997 e_callerinfo.present = e_ext.callerid_present;
1998 e_callerinfo.ntype = e_ext.callerid_type;
2000 e_callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
2002 e_connectedmode = 1; /* dtmf-hangup & disconnect prevention */
2005 /* check if caller id is NOT authenticated */
2006 if (!parse_callbackauth(e_ext.number, &e_callbackinfo)) {
2007 /* make call state to enter password */
2008 new_state(EPOINT_STATE_IN_OVERLAP);
2009 e_action = &action_password_write;
2010 unsched_timer(&e_match_timeout);
2011 e_match_to_action = NULL;
2012 e_dialinginfo.id[0] = '\0';
2013 e_extdialing = strchr(e_dialinginfo.id, '\0');
2014 schedule_timer(&e_password_timeout, 20, 0);
2017 /* incoming call (callback) */
2018 e_ruleset = ruleset_main;
2020 e_rule = e_ruleset->rule_first;
2022 e_extdialing = e_dialinginfo.id;
2023 if (e_dialinginfo.id[0]) {
2024 set_tone(portlist, "dialing");
2027 set_tone(portlist, "dialpbx");
2030 } else { /* testcall */
2031 set_tone(portlist, "hold");
2034 /* start recording if enabled, not when answering machine answers */
2035 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)) {
2036 /* check if we are a terminal */
2037 if (e_ext.number[0] == '\0')
2038 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
2040 port = find_port_id(portlist->port_id);
2042 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
2047 /* port MESSAGE_DISCONNECT MESSAGE_RELEASE */
2048 void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
2050 struct lcr_msg *message;
2052 unsigned int port_id = portlist->port_id;
2056 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2058 /* signal to call tool */
2059 admin_call_response(e_adminid, (message_type==MESSAGE_DISCONNECT)?ADMIN_CALL_DISCONNECT:ADMIN_CALL_RELEASE, "", param->disconnectinfo.cause, param->disconnectinfo.location, 0);
2061 //#warning does this work? only disconnect when incoming port hat not already disconnected yet?
2062 if (e_state==EPOINT_STATE_IN_DISCONNECT && message_type!=MESSAGE_RELEASE){ // || e_state==EPOINT_STATE_OUT_DISCONNECT || e_state==EPOINT_STATE_IDLE)
2063 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are already disconnected.\n", ea_endpoint->ep_serial);
2068 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);
2069 collect_cause(&e_multipoint_cause, &e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location);
2070 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new multipoint cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location);
2072 /* check if we have more than one portlist relation and we just ignore the disconnect */
2073 if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist->next) {
2074 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the disconnect was from a multipoint call. we just release that relation.\n", ea_endpoint->ep_serial);
2075 portlist = ea_endpoint->ep_portlist;
2077 if (portlist->port_id == port_id)
2079 portlist = portlist->next;
2082 FATAL("EPOINT(%d) no portlist related to the calling port.\n", ea_endpoint->ep_serial);
2083 if (message_type != MESSAGE_RELEASE) {
2084 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2085 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2086 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2087 message_put(message);
2088 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2090 ea_endpoint->free_portlist(portlist);
2091 return; /* one relation removed */
2093 if (e_state == EPOINT_STATE_CONNECT) {
2094 /* use cause from port after connect */
2095 cause = param->disconnectinfo.cause;
2096 location = param->disconnectinfo.location;
2098 /* use multipoint cause if no connect yet */
2099 if (e_multipoint_cause) {
2100 cause = e_multipoint_cause;
2101 location = e_multipoint_location;
2103 cause = CAUSE_NOUSER;
2104 location = LOCATION_PRIVATE_LOCAL;
2108 unsched_timer(&e_cfnr_timeout);
2109 unsched_timer(&e_cfnr_call_timeout);
2111 /* process hangup */
2112 process_hangup(e_join_cause, e_join_location);
2113 e_multipoint_cause = 0;
2114 e_multipoint_location = 0;
2116 if (message_type == MESSAGE_DISCONNECT) {
2117 /* tone to disconnected end */
2118 SPRINT(buffer, "cause_%02x", cause);
2119 if (ea_endpoint->ep_portlist)
2120 set_tone(ea_endpoint->ep_portlist, buffer);
2122 new_state(EPOINT_STATE_IN_DISCONNECT);
2125 if (ea_endpoint->ep_join_id) {
2126 int haspatterns = 0;
2127 /* check if pattern is available */
2128 if (ea_endpoint->ep_portlist)
2129 if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->early_b)
2130 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
2131 && message_type != MESSAGE_RELEASE) // if we release, we are done
2134 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has patterns.\n", ea_endpoint->ep_serial);
2135 /* indicate patterns */
2136 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2137 message_put(message);
2138 /* connect audio, if not already */
2139 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2140 message->param.audiopath = 1;
2141 message_put(message);
2142 /* send disconnect */
2143 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2144 memcpy(&message->param, param, sizeof(union parameter));
2145 message_put(message);
2146 /* disable encryption if disconnected */
2147 //PERROR("REMOVE ME: state =%d, %d\n", e_crypt_state, e_crypt);
2150 cryptman_message(CI_DISCONNECT_IND, NULL, 0);
2154 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
2157 if (message_type == MESSAGE_RELEASE)
2158 ea_endpoint->free_portlist(portlist);
2159 release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, callcause, portcause */
2160 return; /* must exit here */
2163 /* port MESSAGE_TIMEOUT */
2164 void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type, union parameter *param)
2168 trace_header("TIMEOUT", DIRECTION_IN);
2169 message_type = MESSAGE_DISCONNECT;
2170 switch (param->state) {
2171 case PORT_STATE_OUT_SETUP:
2172 case PORT_STATE_OUT_OVERLAP:
2173 add_trace("state", NULL, "outgoing setup/dialing");
2175 /* no user responding */
2176 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2177 return; /* must exit here */
2179 case PORT_STATE_IN_SETUP:
2180 case PORT_STATE_IN_OVERLAP:
2181 add_trace("state", NULL, "incoming setup/dialing");
2182 param->disconnectinfo.cause = CAUSE_INVALID; /* number incomplete */
2183 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2186 case PORT_STATE_OUT_PROCEEDING:
2187 add_trace("state", NULL, "outgoing proceeding");
2189 param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
2190 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2191 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2192 return; /* must exit here */
2194 case PORT_STATE_IN_PROCEEDING:
2195 add_trace("state", NULL, "incoming proceeding");
2196 param->disconnectinfo.cause = CAUSE_NOUSER;
2197 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL; /* no user responding */
2200 case PORT_STATE_OUT_ALERTING:
2201 add_trace("state", NULL, "outgoing alerting");
2203 param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
2204 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2205 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2206 return; /* must exit here */
2208 case PORT_STATE_CONNECT:
2209 add_trace("state", NULL, "connect");
2211 param->disconnectinfo.cause = CAUSE_NORMAL; /* normal */
2212 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2213 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2214 return; /* must exit here */
2216 case PORT_STATE_IN_ALERTING:
2217 add_trace("state", NULL, "incoming alerting");
2218 param->disconnectinfo.cause = CAUSE_NOANSWER;
2219 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2222 case PORT_STATE_IN_DISCONNECT:
2223 case PORT_STATE_OUT_DISCONNECT:
2224 add_trace("state", NULL, "disconnect");
2226 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
2227 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2228 return; /* must exit here */
2231 param->disconnectinfo.cause = 31; /* normal unspecified */
2232 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2235 /* release call, disconnect isdn */
2237 new_state(EPOINT_STATE_OUT_DISCONNECT);
2238 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2239 SCPY(e_tone, cause);
2241 set_tone(portlist, cause);
2242 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2243 portlist = portlist->next;
2245 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
2248 /* port MESSAGE_NOTIFY */
2249 void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, union parameter *param)
2251 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2253 struct lcr_msg *message;
2255 /* signal to call tool */
2256 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);
2257 if (param->notifyinfo.notify) {
2258 e_rx_state = track_notify(e_rx_state, param->notifyinfo.notify);
2261 /* if we get notification from stack, local shows if we disabled/enabled audio stream */
2262 if (param->notifyinfo.local) switch(param->notifyinfo.notify) {
2263 case INFO_NOTIFY_REMOTE_HOLD:
2264 case INFO_NOTIFY_USER_SUSPENDED:
2265 /* tell call about it */
2266 if (ea_endpoint->ep_join_id) {
2267 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2268 message->param.audiopath = 0;
2269 message_put(message);
2273 case INFO_NOTIFY_REMOTE_RETRIEVAL:
2274 case INFO_NOTIFY_USER_RESUMED:
2275 /* set volume of rx and tx */
2276 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
2277 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
2279 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2280 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2281 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
2282 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
2283 message_put(message);
2285 /* set current tone */
2287 set_tone(portlist, e_tone);
2288 /* tell call about it */
2289 if (ea_endpoint->ep_join_id) {
2290 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2291 message->param.audiopath = 1;
2292 message_put(message);
2297 /* notify call if available */
2298 if (ea_endpoint->ep_join_id) {
2299 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOTIFY);
2300 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
2301 message_put(message);
2306 /* port MESSAGE_PROGRESS */
2307 void EndpointAppPBX::port_progress(struct port_list *portlist, int message_type, union parameter *param)
2309 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2311 struct lcr_msg *message;
2313 /* signal to call tool */
2314 admin_call_response(e_adminid, ADMIN_CALL_PROGRESS, "", 0, param->progressinfo.location, param->progressinfo.progress);
2316 /* send progress to call if available */
2317 if (ea_endpoint->ep_join_id) {
2318 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PROGRESS);
2319 memcpy(&message->param.progressinfo, ¶m->progressinfo, sizeof(struct progress_info));
2320 message_put(message);
2325 /* port MESSAGE_FACILITY */
2326 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
2328 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2330 struct lcr_msg *message;
2332 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_FACILITY);
2333 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2334 message_put(message);
2337 /* port MESSAGE_3PTY */
2338 void EndpointAppPBX::port_3pty(struct port_list *portlist, int message_type, union parameter *param)
2340 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2342 struct lcr_msg *message;
2346 if (param->threepty.begin)
2347 rc = join_3pty_dss1();
2348 else if (param->threepty.end)
2353 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_3PTY);
2354 message->param.threepty.begin = param->threepty.begin;
2355 message->param.threepty.end = param->threepty.end;
2357 message->param.threepty.error = 1;
2359 message->param.threepty.result = 1;
2360 message->param.threepty.invoke_id = param->threepty.invoke_id;
2361 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2362 message_put(message);
2365 /* port MESSAGE_TRANSFER */
2366 void EndpointAppPBX::port_transfer(struct port_list *portlist, int message_type, union parameter *param)
2368 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2372 /* bridge for real */
2373 if (!(port = find_port_id(portlist->port_id)))
2375 if ((port->p_type & PORT_CLASS_POTS_MASK) == PORT_CLASS_POTS_FXS)
2377 else if ((port->p_type & PORT_CLASS_mISDN_MASK) == PORT_CLASS_DSS1)
2381 /* port MESSAGE_SUSPEND */
2382 /* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
2383 void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
2385 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2387 /* epoint is now parked */
2388 ea_endpoint->ep_park = 1;
2389 memcpy(ea_endpoint->ep_park_callid, param->parkinfo.callid, sizeof(ea_endpoint->ep_park_callid));
2390 ea_endpoint->ep_park_len = (param->parkinfo.len>8)?8:param->parkinfo.len;
2392 /* remove port relation */
2393 ea_endpoint->free_portlist(portlist);
2396 /* port MESSAGE_RESUME */
2397 /* NOTE: before resume, the active-notification must be done in order to set call mixer */
2398 void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
2400 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2402 /* epoint is now resumed */
2403 ea_endpoint->ep_park = 0;
2407 /* port MESSAGE_ENABLEKEYPAD */
2408 void EndpointAppPBX::port_enablekeypad(struct port_list *portlist, int message_type, union parameter *param)
2410 struct lcr_msg *message;
2412 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2414 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_ENABLEKEYPAD);
2415 memcpy(&message->param, param, sizeof(union parameter));
2416 message_put(message);
2420 /* port MESSAGE_DISABLE_DEJITTER */
2421 void EndpointAppPBX::port_disable_dejitter(struct port_list *portlist, int message_type, union parameter *param)
2423 struct lcr_msg *message;
2425 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2427 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_DISABLE_DEJITTER);
2428 memcpy(&message->param, param, sizeof(union parameter));
2429 message_put(message);
2433 /* port sends message to the endpoint
2435 void EndpointAppPBX::ea_message_port(unsigned int port_id, int message_type, union parameter *param)
2437 struct port_list *portlist;
2439 portlist = ea_endpoint->ep_portlist;
2441 if (port_id == portlist->port_id)
2443 portlist = portlist->next;
2446 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);
2450 // PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
2451 switch(message_type) {
2452 case MESSAGE_TONE_EOF: /* tone is end of file */
2453 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
2455 if (e_action->index == ACTION_VBOX_PLAY) {
2458 if (e_action->index == ACTION_EFI) {
2464 case MESSAGE_TONE_COUNTER: /* counter info received */
2465 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);
2467 if (e_action->index == ACTION_VBOX_PLAY) {
2468 e_vbox_counter = param->counter.current;
2469 if (param->counter.max >= 0)
2470 e_vbox_counter_max = param->counter.max;
2474 /* PORT sends SETUP message */
2476 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);
2477 if (e_state!=EPOINT_STATE_IDLE) {
2478 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
2481 port_setup(portlist, message_type, param);
2484 /* PORT sends INFORMATION message */
2485 case MESSAGE_INFORMATION: /* additional digits received */
2486 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);
2487 port_information(portlist, message_type, param);
2490 /* PORT sends FACILITY message */
2491 case MESSAGE_FACILITY:
2492 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2493 port_facility(portlist, message_type, param);
2497 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming 3PTY facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2498 port_3pty(portlist, message_type, param);
2501 case MESSAGE_TRANSFER:
2502 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming TRANSFER request (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2503 port_transfer(portlist, message_type, param);
2506 /* PORT sends DTMF message */
2507 case MESSAGE_DTMF: /* dtmf digits received */
2508 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);
2509 port_dtmf(portlist, message_type, param);
2512 /* PORT sends CRYPT message */
2513 case MESSAGE_CRYPT: /* crypt response received */
2514 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) crypt response=%d\n", ea_endpoint->ep_serial, param->crypt.type);
2515 port_crypt(portlist, message_type, param);
2518 /* PORT sends MORE message */
2519 case MESSAGE_OVERLAP:
2520 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);
2521 if (e_state != EPOINT_STATE_OUT_SETUP) {
2522 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);
2525 port_overlap(portlist, message_type, param);
2528 /* PORT sends PROCEEDING message */
2529 case MESSAGE_PROCEEDING: /* port is proceeding */
2530 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);
2531 if (e_state!=EPOINT_STATE_OUT_SETUP
2532 && e_state!=EPOINT_STATE_OUT_OVERLAP) {
2533 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);
2536 port_proceeding(portlist, message_type, param);
2539 /* PORT sends ALERTING message */
2540 case MESSAGE_ALERTING:
2541 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);
2542 if (e_state!=EPOINT_STATE_OUT_SETUP
2543 && e_state!=EPOINT_STATE_OUT_OVERLAP
2544 && e_state!=EPOINT_STATE_OUT_PROCEEDING) {
2545 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);
2548 port_alerting(portlist, message_type, param);
2551 /* PORT sends CONNECT message */
2552 case MESSAGE_CONNECT:
2553 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);
2554 if (e_state!=EPOINT_STATE_OUT_SETUP
2555 && e_state!=EPOINT_STATE_OUT_OVERLAP
2556 && e_state!=EPOINT_STATE_OUT_PROCEEDING
2557 && e_state!=EPOINT_STATE_OUT_ALERTING) {
2558 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
2561 port_connect(portlist, message_type, param);
2564 /* PORT sends DISCONNECT message */
2565 case MESSAGE_DISCONNECT: /* port is disconnected */
2566 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);
2567 port_disconnect_release(portlist, message_type, param);
2570 /* PORT sends a RELEASE message */
2571 case MESSAGE_RELEASE: /* port releases */
2572 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);
2573 /* portlist is release at port_disconnect_release, thanx Paul */
2574 port_disconnect_release(portlist, message_type, param);
2577 /* PORT sends a TIMEOUT message */
2578 case MESSAGE_TIMEOUT:
2579 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);
2580 port_timeout(portlist, message_type, param);
2581 break; /* release */
2583 /* PORT sends a NOTIFY message */
2584 case MESSAGE_NOTIFY:
2585 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);
2586 port_notify(portlist, message_type, param);
2589 /* PORT sends a PROGRESS message */
2590 case MESSAGE_PROGRESS:
2591 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);
2592 port_progress(portlist, message_type, param);
2595 /* PORT sends a SUSPEND message */
2596 case MESSAGE_SUSPEND:
2597 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);
2598 port_suspend(portlist, message_type, param);
2599 break; /* suspend */
2601 /* PORT sends a RESUME message */
2602 case MESSAGE_RESUME:
2603 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);
2604 port_resume(portlist, message_type, param);
2608 kann nach dem test gelöscht werden, da eine direkte funktion im join und im mISDN zum austausch der message existiert
2609 /* port assigns bchannel */
2610 case MESSAGE_BCHANNEL: /* bchannel assignment messafe */
2611 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);
2612 /* only one port is expected to be connected to bchannel */
2613 message = message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2614 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_IN);
2618 /* PORT requests DTMF */
2619 case MESSAGE_ENABLEKEYPAD:
2620 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);
2621 port_enablekeypad(portlist, message_type, param);
2624 case MESSAGE_DISABLE_DEJITTER:
2625 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming disable dejitter message (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2626 port_disable_dejitter(portlist, message_type, param);
2631 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);
2634 /* Note: this endpoint may be destroyed, so we MUST return */
2638 /* messages from join
2640 /* join MESSAGE_CRYPT */
2641 void EndpointAppPBX::join_crypt(struct port_list *portlist, int message_type, union parameter *param)
2644 switch(param->crypt.type) {
2645 /* message from remote port to "crypt manager" */
2646 case CU_ACTK_REQ: /* activate key-exchange */
2647 case CU_ACTS_REQ: /* activate shared key */
2648 case CU_DACT_REQ: /* deactivate */
2649 case CU_INFO_REQ: /* request last info message */
2650 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2653 /* message from "crypt manager" to user */
2654 case CU_ACTK_CONF: /* key-echange done */
2655 case CU_ACTS_CONF: /* shared key done */
2656 case CU_DACT_CONF: /* deactivated */
2657 case CU_DACT_IND: /* deactivated */
2658 case CU_ERROR_IND: /* receive error message */
2659 case CU_INFO_IND: /* receive info message */
2660 case CU_INFO_CONF: /* receive info message */
2661 encrypt_result(param->crypt.type, (char *)param->crypt.data);
2665 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);
2670 /* join MESSAGE_INFORMATION */
2671 void EndpointAppPBX::join_information(struct port_list *portlist, int message_type, union parameter *param)
2673 struct lcr_msg *message;
2678 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2679 memcpy(&message->param.information, ¶m->information, sizeof(struct dialing_info));
2680 message_put(message);
2681 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2682 portlist = portlist->next;
2686 /* join MESSAGE_FACILITY */
2687 void EndpointAppPBX::join_facility(struct port_list *portlist, int message_type, union parameter *param)
2689 struct lcr_msg *message;
2691 if (!e_ext.facility && e_ext.number[0]) {
2696 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_FACILITY);
2697 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2698 message_put(message);
2699 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2700 portlist = portlist->next;
2704 /* join MESSAGE_MORE */
2705 void EndpointAppPBX::join_overlap(struct port_list *portlist, int message_type, union parameter *param)
2707 struct lcr_msg *message;
2709 new_state(EPOINT_STATE_IN_OVERLAP);
2712 if (e_join_pattern && e_ext.own_setup) {
2713 /* disconnect audio */
2714 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2715 message->param.audiopath = 0;
2716 message_put(message);
2718 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL) {
2719 if (e_dialinginfo.id[0])
2720 set_tone(portlist, "dialing");
2722 set_tone(portlist, "dialtone");
2725 if (e_dialinginfo.id[0]) {
2726 set_tone(portlist, "dialing");
2728 if (e_ext.number[0])
2729 set_tone(portlist, "dialpbx");
2731 set_tone(portlist, "dialtone");
2735 /* join MESSAGE_PROCEEDING */
2736 void EndpointAppPBX::join_proceeding(struct port_list *portlist, int message_type, union parameter *param)
2738 struct lcr_msg *message;
2740 new_state(EPOINT_STATE_IN_PROCEEDING);
2742 /* own proceeding tone */
2743 if (e_join_pattern) {
2744 /* connect / disconnect audio */
2745 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2746 if (e_ext.own_proceeding)
2747 message->param.audiopath = 0;
2749 message->param.audiopath = 1;
2750 message_put(message);
2752 // UCPY(e_join_tone, "proceeding");
2754 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
2755 message_put(message);
2756 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2758 set_tone(portlist, "proceeding");
2761 /* join MESSAGE_ALERTING */
2762 void EndpointAppPBX::join_alerting(struct port_list *portlist, int message_type, union parameter *param)
2764 struct lcr_msg *message;
2766 new_state(EPOINT_STATE_IN_ALERTING);
2768 /* own alerting tone */
2769 if (e_join_pattern) {
2770 /* connect / disconnect audio */
2771 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2772 if (e_ext.own_alerting)
2773 message->param.audiopath = 0;
2775 message->param.audiopath = 1;
2776 message_put(message);
2779 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
2780 message_put(message);
2781 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2783 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL) {
2784 set_tone(portlist, "ringing");
2787 if (e_ext.number[0])
2788 set_tone(portlist, "ringpbx");
2790 set_tone(portlist, "ringing");
2792 if (e_ext.number[0])
2793 e_dtmf = 1; /* allow dtmf */
2796 /* join MESSAGE_CONNECT */
2797 void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type, union parameter *param)
2799 struct lcr_msg *message;
2802 new_state(EPOINT_STATE_CONNECT);
2803 // UCPY(e_join_tone, "");
2805 if (e_ext.number[0])
2806 e_dtmf = 1; /* allow dtmf */
2809 unsched_timer(&e_powerdial_timeout);
2810 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_callerinfo));
2812 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
2813 memcpy(&message->param, param, sizeof(union parameter));
2815 /* screen clip if prefix is required */
2816 if (e_ext.number[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0]) {
2817 SCPY(message->param.connectinfo.id, e_ext.clip_prefix);
2818 SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype, options.national, options.international));
2819 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2822 /* use internal caller id */
2823 if (e_ext.number[0] && e_connectinfo.extension[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore)) {
2824 SCPY(message->param.connectinfo.id, e_connectinfo.extension);
2825 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2828 /* handle restricted caller ids */
2829 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);
2830 /* display callerid if desired for extension */
2831 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));
2833 /* use conp, if enabld */
2834 // if (!e_ext.centrex)
2835 // message->param.connectinfo.name[0] = '\0';
2838 message_put(message);
2839 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2841 set_tone(portlist, NULL);
2843 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2844 message->param.audiopath = 1;
2845 message_put(message);
2850 /* join MESSAGE_DISCONNECT MESSAGE_RELEASE */
2851 void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *param)
2854 struct lcr_msg *message;
2855 struct port_list *portlist = NULL;
2859 /* be sure that we are active */
2861 e_tx_state = NOTIFY_STATE_ACTIVE;
2863 /* we are powerdialing, if e_powerdial_on is set and limit is not exceeded if given */
2864 if (e_powerdial_on && ((e_powercount+1)<e_powerlimit || e_powerlimit<1)) {
2865 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL,0 ); /* RELEASE_TYPE, join, port */
2867 /* set time for power dialing */
2868 schedule_timer(&e_powerdial_timeout, (int)e_powerdelay, 0); /* set redial in the future */
2871 /* set redial tone */
2872 if (ea_endpoint->ep_portlist) {
2875 set_tone(ea_endpoint->ep_portlist, "redial");
2876 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);
2877 /* send proceeding when powerdialing and still setup (avoid dialing timeout) */
2878 if (e_state==EPOINT_STATE_IN_OVERLAP) {
2879 new_state(EPOINT_STATE_IN_PROCEEDING);
2880 if (ea_endpoint->ep_portlist) {
2881 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
2882 message_put(message);
2883 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
2885 /* caused the error, that the first knock sound was not there */
2886 /* set_tone(portlist, "proceeding"); */
2888 /* send display of powerdialing */
2889 if (e_ext.display_dialing) {
2890 portlist = ea_endpoint->ep_portlist;
2892 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
2894 SPRINT(message->param.notifyinfo.display, "Retry %d of %d", e_powercount, e_powerlimit);
2896 SPRINT(message->param.notifyinfo.display, "Retry %d", e_powercount);
2897 message_put(message);
2898 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2899 portlist = portlist->next;
2909 if ((e_state!=EPOINT_STATE_CONNECT
2910 && e_state!=EPOINT_STATE_OUT_DISCONNECT
2911 && e_state!=EPOINT_STATE_IN_OVERLAP
2912 && e_state!=EPOINT_STATE_IN_PROCEEDING
2913 && e_state!=EPOINT_STATE_IN_ALERTING)
2914 || !ea_endpoint->ep_portlist) { /* or no port */
2915 process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
2916 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause, 0); /* RELEASE_TYPE, join, port */
2917 return; /* must exit here */
2920 if (!e_join_cause) {
2921 e_join_cause = param->disconnectinfo.cause;
2922 e_join_location = param->disconnectinfo.location;
2925 /* on release we need the audio again! */
2926 if (message_type == MESSAGE_RELEASE) {
2928 ea_endpoint->ep_join_id = 0;
2930 /* disconnect and select tone */
2931 new_state(EPOINT_STATE_OUT_DISCONNECT);
2932 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2933 /* if own_cause, we must release the join */
2934 if (e_ext.own_cause /* own cause */
2935 || !e_join_pattern) { /* no patterns */
2936 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);
2937 if (message_type != MESSAGE_RELEASE)
2938 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
2940 } else { /* else we enable audio */
2941 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2942 message->param.audiopath = 1;
2943 message_put(message);
2945 /* send disconnect message */
2946 SCPY(e_tone, cause);
2947 portlist = ea_endpoint->ep_portlist;
2949 set_tone(portlist, cause);
2950 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2951 portlist = portlist->next;
2955 /* join MESSAGE_SETUP */
2956 void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, union parameter *param)
2958 struct lcr_msg *message;
2959 // struct interface *interface;
2961 /* if we already in setup state, we just update the dialing with new digits */
2962 if (e_state == EPOINT_STATE_OUT_SETUP
2963 || e_state == EPOINT_STATE_OUT_OVERLAP) {
2964 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we are in setup state, so we do overlap dialing.\n", ea_endpoint->ep_serial);
2965 /* if digits changed, what we have already dialed */
2966 if (!!strncmp(e_dialinginfo.id,param->setup.dialinginfo.id,strlen(e_dialinginfo.id))) {
2967 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);
2968 /* release all ports */
2969 while((portlist = ea_endpoint->ep_portlist)) {
2970 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2971 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2972 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2973 message_put(message);
2974 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2975 ea_endpoint->free_portlist(portlist);
2978 /* disconnect audio */
2979 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2980 message->param.audiopath = 0;
2981 message_put(message);
2983 /* get dialing info */
2984 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
2985 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
2986 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
2987 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
2988 new_state(EPOINT_STATE_OUT_OVERLAP);
2991 schedule_timer(&e_redial_timeout, 1, 0);
2994 /* if we have a pending redial, so we just adjust the dialing number */
2995 if (e_redial_timeout.active) {
2996 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);
2997 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3000 if (!ea_endpoint->ep_portlist) {
3001 PERROR("ERROR: overlap dialing to a NULL port relation\n");
3003 if (ea_endpoint->ep_portlist->next) {
3004 PERROR("ERROR: overlap dialing to a port_list port relation\n");
3006 if (e_state == EPOINT_STATE_OUT_SETUP) {
3008 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);
3009 SCAT(e_dialing_queue, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3012 /* get what we have not dialed yet */
3013 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));
3014 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
3015 SCPY(message->param.information.id, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3016 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
3017 message_put(message);
3018 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3020 /* always store what we have dialed or queued */
3021 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3025 if (e_state != EPOINT_STATE_IDLE) {
3026 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
3029 /* if an internal extension is dialed, copy that number */
3030 if (param->setup.dialinginfo.itype==INFO_ITYPE_ISDN_EXTENSION || param->setup.dialinginfo.itype==INFO_ITYPE_VBOX)
3031 SCPY(e_ext.number, param->setup.dialinginfo.id);
3032 /* if an internal extension is dialed, get extension's info about caller */
3033 if (e_ext.number[0]) {
3034 if (!read_extension(&e_ext, e_ext.number)) {
3035 e_ext.number[0] = '\0';
3036 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the called terminal='%s' is not found in directory tree!\n", ea_endpoint->ep_serial, e_ext.number);
3040 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3041 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3042 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3043 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3044 memcpy(&e_rtpinfo, ¶m->setup.rtpinfo, sizeof(e_rtpinfo));
3046 /* process (voice over) data calls */
3047 if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO) {
3048 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) handling data call as audio call: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
3049 memset(&e_capainfo, 0, sizeof(e_capainfo));
3050 e_capainfo.bearer_capa = INFO_BC_AUDIO;
3051 e_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
3052 e_capainfo.bearer_info1 = (options.law=='u')?INFO_INFO1_ULAW:INFO_INFO1_ALAW;
3055 new_state(EPOINT_STATE_OUT_SETUP);
3056 /* call special setup routine */