1 /*****************************************************************************\
3 ** Linux Call Router **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
8 ** The EndpointAppPBX implements PBX4Linux **
10 \*****************************************************************************/
15 class EndpointAppPBX *apppbx_first = NULL;
18 * EndpointAppPBX constructor
20 EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint, int origin) : EndpointApp(epoint, origin)
22 class EndpointAppPBX **apppointer;
24 /* add application to chain */
26 apppointer = &apppbx_first;
28 apppointer = &((*apppointer)->next);
32 memset(&e_ext, 0, sizeof(struct extension));
33 // *************** NOTE: also change value in read_extension() **************
34 e_ext.rights = 4; /* international */
35 e_ext.rx_gain = e_ext.tx_gain = 0;
36 e_state = EPOINT_STATE_IDLE;
37 e_ext.number[0] = '\0';
38 e_extension_interface[0] = '\0';
39 memset(&e_callerinfo, 0, sizeof(struct caller_info));
40 memset(&e_dialinginfo, 0, sizeof(struct dialing_info));
41 memset(&e_connectinfo, 0, sizeof(struct connect_info));
42 memset(&e_redirinfo, 0, sizeof(struct redir_info));
43 memset(&e_capainfo, 0, sizeof(struct capa_info));
46 e_ruleset = ruleset_main;
48 e_rule = e_ruleset->rule_first;
53 e_match_to_action = NULL;
55 e_extdialing = e_dialinginfo.id;
59 // e_join_tone[0] = e_hold_tone[0] = '\0';
60 e_join_pattern /*= e_hold_pattern*/ = 0;
63 e_adminid = 0; // will be set, if call was initiated via admin socket
68 e_cbdialing[0] = '\0';
71 memset(&e_callbackinfo, 0, sizeof(struct caller_info));
79 e_password_timeout = 0;
80 e_multipoint_cause = 0;
81 e_multipoint_location = 0;
82 e_dialing_queue[0] = '\0';
84 e_crypt_state = CM_ST_NULL;
85 e_crypt_keyengine_busy = 0;
86 e_crypt_info[0] = '\0';
89 e_tx_state = NOTIFY_STATE_ACTIVE;
90 e_rx_state = NOTIFY_STATE_ACTIVE;
91 e_join_cause = e_join_location = 0;
92 /*********************************
93 *********************************
94 ********* ATTENTION *************
95 *********************************
96 *********************************/
97 /* if you add new values, that must be initialized, also check if they must
98 * be initialized when doing callback
104 * EpointAppPBX destructor
106 EndpointAppPBX::~EndpointAppPBX(void)
108 class EndpointAppPBX *temp, **tempp;
112 tempp = &apppbx_first;
122 FATAL("Endpoint not in endpoint's list.\n");
129 * trace header for application
131 void EndpointAppPBX::trace_header(char *name, int direction)
135 char msgtext[sizeof(_trace.name)];
139 /* init trace with given values */
142 numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype, options.national, options.international),
146 ea_endpoint->ep_serial,
153 /* set new endpoint state
155 void EndpointAppPBX::new_state(int state)
158 if (e_state != state)
160 trace_header("NEW STATE", DIRECTION_NONE);
161 add_trace("state", "old", "%s", state_name[e_state]);
162 add_trace("state", "new", "%s", state_name[state]);
170 /* release join and port (as specified)
172 void EndpointAppPBX::release(int release, int joinlocation, int joincause, int portlocation, int portcause)
174 struct port_list *portlist;
175 struct lcr_msg *message;
178 /* message to test call */
179 admin_call_response(e_adminid, ADMIN_CALL_RELEASE, "", joincause, joinlocation, 0);
181 /* if a release is pending */
182 if (release==RELEASE_JOIN || release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY)
184 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): do pending release (joincause %d location %d)\n", ea_endpoint->ep_serial, joincause, joinlocation);
185 if (ea_endpoint->ep_join_id)
187 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_RELEASE);
188 message->param.disconnectinfo.cause = joincause;
189 message->param.disconnectinfo.location = joinlocation;
190 message_put(message);
191 ea_endpoint->ep_join_id = 0;
195 if (release != RELEASE_PORT_JOINONLY)
198 join_release(e_hold_id, ea_endpoint->ep_serial, 1, joinlocation, joincause);
203 if (release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY)
205 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release (portcause %d portlocation)\n", ea_endpoint->ep_serial, portcause, portlocation);
206 while((portlist = ea_endpoint->ep_portlist))
208 if (portlist->port_id)
210 SPRINT(cause, "cause_%02x", portcause);
211 set_tone(portlist, cause);
212 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
213 message->param.disconnectinfo.cause = portcause;
214 message->param.disconnectinfo.location = portlocation;
215 message_put(message);
216 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
218 ea_endpoint->free_portlist(portlist);
221 /* if callback is enabled, call back with the given caller id */
224 /* reset some stuff */
225 new_state(EPOINT_STATE_IDLE);
226 memset(&e_connectinfo, 0, sizeof(struct connect_info));
227 memset(&e_redirinfo, 0, sizeof(struct redir_info));
228 e_start = e_stop = 0;
229 e_ruleset = ruleset_main;
231 e_rule = e_ruleset->rule_first;
233 e_action_timeout = 0;
235 e_match_to_action = NULL;
237 e_extdialing = e_dialinginfo.id;
245 e_multipoint_cause = 0;
246 e_multipoint_location = 0;
247 e_dialing_queue[0] = '\0';
249 e_crypt_state = CM_ST_NULL;
250 e_crypt_keyengine_busy = 0;
251 e_crypt_info[0] = '\0';
255 e_tx_state = NOTIFY_STATE_ACTIVE;
256 e_rx_state = NOTIFY_STATE_ACTIVE;
257 e_join_cause = e_join_location = 0;
259 /* the caller info of the callback user */
260 memcpy(&e_callbackinfo, &e_callerinfo, sizeof(e_callbackinfo));
261 memset(&e_dialinginfo, 0, sizeof(e_dialinginfo));
262 /* create dialing by callerinfo */
263 if (e_ext.number[0] && e_extension_interface[0])
265 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to internal: %s interface %s\n", ea_endpoint->ep_serial, e_ext.number, e_extension_interface);
266 /* create callback to the current terminal */
267 SCPY(e_dialinginfo.id, e_ext.number);
268 SCPY(e_dialinginfo.interfaces, e_extension_interface);
269 e_dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
270 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
275 SCPY(e_dialinginfo.id, e_cbto);
278 /* numberrize caller id and use it to dial to the callback */
279 SCPY(e_dialinginfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype, options.national, options.international));
281 e_dialinginfo.itype = INFO_ITYPE_ISDN;
282 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
283 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to external: %s\n", ea_endpoint->ep_serial, e_dialinginfo.id);
288 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release of epoint itself.\n", ea_endpoint->ep_serial);
289 ea_endpoint->ep_use--; /* when e_lock is 0, the endpoint will be deleted */
295 /* cancel callerid if restricted, unless anon-ignore is enabled at extension or port is of type external (so called police gets caller id :)*/
296 void apply_callerid_restriction(struct extension *ext, char *id, int *ntype, int *present, int *screen, char *extension, char *name)
298 PDEBUG(DEBUG_EPOINT, "id='%s' ntype=%d present=%d screen=%d extension='%s' name='%s'\n", (id)?id:"NULL", (ntype)?*ntype:-1, (present)?*present:-1, (screen)?*screen:-1, (extension)?extension:"NULL", (name)?name:"NULL");
300 /* caller id is not restricted, so we do nothing */
301 if (*present != INFO_PRESENT_RESTRICTED)
304 /* only extensions are restricted */
308 /* if we enabled anonymouse ignore */
309 if (ext->anon_ignore)
312 /* else we remove the caller id */
316 *ntype = INFO_NTYPE_UNKNOWN;
318 // *screen = INFO_SCREEN_USER;
319 // maybe we should not make voip address anonymous
322 // maybe it's no fraud to present extension id
324 // extension[0] = '\0';
329 /* used display message to display callerid as available */
330 char *EndpointAppPBX::apply_callerid_display(char *id, int itype, int ntype, int present, int screen, char *extension, char *name)
332 static char display[81];
335 char *cid = numberrize_callerinfo(id, ntype, options.national, options.international);
337 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) id='%s' itype=%d ntype=%d present=%d screen=%d extension='%s' name='%s'\n", ea_endpoint->ep_serial, (id)?id:"NULL", itype, ntype, present, screen, (extension)?extension:"NULL", (name)?name:"NULL");
346 /* NOTE: is caller is is not available for this extesion, it has been removed by apply_callerid_restriction already */
348 /* internal extension's caller id */
349 if (extension[0] && e_ext.display_int)
352 SCAT(display, extension);
355 if (itype == INFO_ITYPE_VBOX)
356 SCAT(display, "(vbox)");
358 SCAT(display, "(int)");
361 /* external caller id */
362 if (!extension[0] && e_ext.display_ext)
368 if (present == INFO_PRESENT_RESTRICTED)
369 SCAT(display, "anonymous");
371 SCAT(display, "unknown");
378 /* display if callerid is anonymouse but available due anon-ignore */
379 if (e_ext.display_anon && present==INFO_PRESENT_RESTRICTED)
382 SCAT(display, "unknown");
385 SCAT(display, " anon");
388 /* display if callerid is anonymouse but available due anon-ignore */
389 if (e_ext.display_fake && screen==INFO_SCREEN_USER && present!=INFO_PRESENT_NULL)
395 if (present == INFO_PRESENT_RESTRICTED)
396 SCAT(display, "anonymous");
398 SCAT(display, "unknown");
403 SCAT(display, " fake");
407 if (name[0] && e_ext.display_name)
409 if (!display[0] && cid[0])
420 * uses the current state to notify activity
422 void EndpointAppPBX::notify_active(void)
424 struct port_list *portlist = ea_endpoint->ep_portlist;
425 struct lcr_msg *message;
430 case NOTIFY_STATE_ACTIVE:
431 /* we are already active, so we don't do anything */
434 case NOTIFY_STATE_SUSPEND:
435 notify = INFO_NOTIFY_USER_RESUMED;
438 set_tone(portlist, NULL);
439 portlist = portlist->next;
441 portlist = ea_endpoint->ep_portlist;
444 case NOTIFY_STATE_HOLD:
445 notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
448 set_tone(portlist, NULL);
449 portlist = portlist->next;
451 portlist = ea_endpoint->ep_portlist;
454 case NOTIFY_STATE_CONFERENCE:
455 notify = INFO_NOTIFY_CONFERENCE_DISCONNECTED;
458 set_tone(portlist, NULL);
459 portlist = portlist->next;
461 portlist = ea_endpoint->ep_portlist;
465 PERROR("unknown e_tx_state = %d\n", e_tx_state);
471 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
472 message->param.notifyinfo.notify = notify;
473 message_put(message);
474 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
475 portlist = portlist->next;
481 * keypad functions during call. one example to use this is to put a call on hold or start a conference
483 void EndpointAppPBX::keypad_function(char digit)
486 /* we must be in a call, in order to send messages to the call */
487 if (e_ext.number[0] == '\0')
489 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) IGNORING keypad received not from extension.\n", ea_endpoint->ep_serial);
495 /* join conference */
497 if (ea_endpoint->ep_join_id == 0)
499 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad received during connect but not during a call.\n", ea_endpoint->ep_serial);
502 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join call with call on hold\n", ea_endpoint->ep_serial);
508 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) shared key encryption selected.\n", ea_endpoint->ep_serial);
512 /* crypt key-exchange */
514 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) key exchange encryption selected.\n", ea_endpoint->ep_serial);
520 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) encryption off selected.\n", ea_endpoint->ep_serial);
525 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) unsupported keypad digit '%c'.\n", ea_endpoint->ep_serial, digit);
530 /* set tone pattern for port */
531 void EndpointAppPBX::set_tone(struct port_list *portlist, char *tone)
533 struct lcr_msg *message;
538 /* store for suspended processes */
542 if (e_join_pattern /* pattern are provided */
543 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_SETUP)
544 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_OVERLAP)
545 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_IN_PROCEEDING)
546 && !(e_ext.own_alerting && e_state == EPOINT_STATE_IN_ALERTING)
547 && !(e_ext.own_cause && e_state == EPOINT_STATE_IN_DISCONNECT)
548 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_SETUP)
549 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_OVERLAP)
550 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_OUT_PROCEEDING)
551 && !(e_ext.own_alerting && e_state == EPOINT_STATE_OUT_ALERTING)
552 && !(e_ext.own_cause && e_state == EPOINT_STATE_OUT_DISCONNECT)
553 && tone[0] && !!strncmp(tone,"crypt_*",6))
555 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) tone not provided since patterns are available\n", ea_endpoint->ep_serial);
561 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_TONE);
562 SCPY(message->param.tone.dir, e_ext.tones_dir[0]?e_ext.tones_dir:options.tones_dir);
563 SCPY(message->param.tone.name, tone);
564 message_put(message);
565 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
568 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port to notify tone.\n", ea_endpoint->ep_serial);
575 * hunts an mISDNport that is available for an outgoing call
576 * if no ifname was given, any interface that is not an extension
579 struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel)
581 struct interface *interface;
582 struct interface_port *ifport, *ifport_start;
583 struct select_channel *selchannel;
584 struct mISDNport *mISDNport;
587 interface = interface_first;
589 /* first find the given interface or, if not given, one with no extension */
594 /* check for given interface */
597 if (!strcasecmp(interface->name, ifname))
599 /* found explicit interface */
600 trace_header("CHANNEL SELECTION (found interface)", DIRECTION_NONE);
601 add_trace("interface", NULL, "%s", ifname);
608 if (!interface->extension)
610 /* found non extension */
611 trace_header("CHANNEL SELECTION (found non extension interface)", DIRECTION_NONE);
612 add_trace("interface", NULL, "%s", interface->name);
618 interface = interface->next;
622 /* see if interface has ports */
623 if (!interface->ifport)
626 trace_header("CHANNEL SELECTION (active ports, skipping)", DIRECTION_NONE);
627 add_trace("interface", NULL, "%s", interface->name);
629 interface = interface->next;
633 /* select port by algorithm */
634 ifport_start = interface->ifport;
636 if (interface->hunt == HUNT_ROUNDROBIN)
638 while(ifport_start->next && index<interface->hunt_next)
640 ifport_start = ifport_start->next;
643 trace_header("CHANNEL SELECTION (starting round-robin)", DIRECTION_NONE);
644 add_trace("port", NULL, "%d", ifport_start->portnum);
645 add_trace("position", NULL, "%d", index);
650 ifport = ifport_start;
653 /* see if port is available */
654 if (!ifport->mISDNport)
656 trace_header("CHANNEL SELECTION (port not available, skipping)", DIRECTION_NONE);
657 add_trace("port", NULL, "%d", ifport->portnum);
658 add_trace("position", NULL, "%d", index);
662 mISDNport = ifport->mISDNport;
664 /* see if port is administratively blocked */
667 trace_header("CHANNEL SELECTION (port blocked by admin, skipping)", DIRECTION_NONE);
668 add_trace("port", NULL, "%d", ifport->portnum);
669 add_trace("position", NULL, "%d", index);
674 /* see if link is up on PTP*/
675 if (mISDNport->l2hold && !mISDNport->l2link)
677 trace_header("CHANNEL SELECTION (port's layer 2 is down, skipping)", DIRECTION_NONE);
678 add_trace("port", NULL, "%d", ifport->portnum);
679 add_trace("position", NULL, "%d", index);
684 /* check for channel form selection list */
686 selchannel = ifport->out_channel;
689 switch(selchannel->channel)
691 case CHANNEL_FREE: /* free channel */
692 if (mISDNport->b_reserved >= mISDNport->b_num)
693 break; /* all channel in use or reserverd */
696 while(i < mISDNport->b_num)
698 if (mISDNport->b_port[i] == NULL)
700 *channel = i+1+(i>=15);
701 trace_header("CHANNEL SELECTION (selecting free channel)", DIRECTION_NONE);
702 add_trace("port", NULL, "%d", ifport->portnum);
703 add_trace("position", NULL, "%d", index);
704 add_trace("channel", NULL, "%d", *channel);
712 trace_header("CHANNEL SELECTION (no channel is 'free')", DIRECTION_NONE);
713 add_trace("port", NULL, "%d", ifport->portnum);
714 add_trace("position", NULL, "%d", index);
718 case CHANNEL_ANY: /* don't ask for channel */
719 if (mISDNport->b_reserved >= mISDNport->b_num)
721 trace_header("CHANNEL SELECTION (cannot ask for 'any' channel, all reserved)", DIRECTION_NONE);
722 add_trace("port", NULL, "%d", ifport->portnum);
723 add_trace("position", NULL, "%d", index);
724 add_trace("total", NULL, "%d", mISDNport->b_num);
725 add_trace("reserved", NULL, "%d", mISDNport->b_reserved);
727 break; /* all channel in use or reserverd */
729 trace_header("CHANNEL SELECTION (using 'any' channel)", DIRECTION_NONE);
730 add_trace("port", NULL, "%d", ifport->portnum);
731 add_trace("position", NULL, "%d", index);
733 *channel = CHANNEL_ANY;
736 case CHANNEL_NO: /* call waiting */
737 trace_header("CHANNEL SELECTION (using 'no' channel, call-waiting)", DIRECTION_NONE);
738 add_trace("port", NULL, "%d", ifport->portnum);
739 add_trace("position", NULL, "%d", index);
741 *channel = CHANNEL_NO;
745 if (selchannel->channel<1 || selchannel->channel==16)
747 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
748 add_trace("port", NULL, "%d", ifport->portnum);
749 add_trace("position", NULL, "%d", index);
750 add_trace("channel", NULL, "%d", selchannel->channel);
752 break; /* invalid channels */
754 i = selchannel->channel-1-(selchannel->channel>=17);
755 if (i >= mISDNport->b_num)
757 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
758 add_trace("port", NULL, "%d", ifport->portnum);
759 add_trace("position", NULL, "%d", index);
760 add_trace("channel", NULL, "%d", selchannel->channel);
761 add_trace("channels", NULL, "%d", mISDNport->b_num);
763 break; /* channel not in port */
765 if (mISDNport->b_port[i] == NULL)
767 *channel = selchannel->channel;
768 trace_header("CHANNEL SELECTION (selecting given channel)", DIRECTION_NONE);
769 add_trace("port", NULL, "%d", ifport->portnum);
770 add_trace("position", NULL, "%d", index);
771 add_trace("channel", NULL, "%d", *channel);
778 break; /* found channel */
779 selchannel = selchannel->next;
782 /* if channel was found, return mISDNport and channel */
785 /* setting next port to start next time */
786 if (interface->hunt == HUNT_ROUNDROBIN)
791 interface->hunt_next = index;
797 trace_header("CHANNEL SELECTION (skipping, no channel found)", DIRECTION_NONE);
798 add_trace("port", NULL, "%d", ifport->portnum);
799 add_trace("position", NULL, "%d", index);
803 /* go next port, until all ports are checked */
805 ifport = ifport->next;
809 ifport = interface->ifport;
811 if (ifport != ifport_start)
815 interface = interface->next;
819 return(NULL); /* no port found */
822 /* outgoing setup to port(s)
823 * ports will be created and a setup is sent if everything is ok. otherwhise
824 * the endpoint is destroyed.
826 void EndpointAppPBX::out_setup(void)
828 struct dialing_info dialinginfo;
830 // class pdss1 *pdss1;
831 struct port_list *portlist;
832 struct lcr_msg *message;
834 int cause = CAUSE_RESSOURCEUNAVAIL;
837 struct mISDNport *mISDNport;
840 class EndpointAppPBX *atemp;
841 // char allowed_ports[256];
843 char ifname[sizeof(e_ext.interfaces)],
845 struct port_settings port_settings;
849 /* create settings for creating port */
850 memset(&port_settings, 0, sizeof(port_settings));
852 SCPY(port_settings.tones_dir, e_ext.tones_dir);
854 SCPY(port_settings.tones_dir, options.tones_dir);
855 port_settings.no_seconds = e_ext.no_seconds;
857 /* 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 */
859 /* check what dialinginfo.itype we got */
860 switch(e_dialinginfo.itype)
862 /* *********************** call to extension or vbox */
863 case INFO_ITYPE_ISDN_EXTENSION:
864 /* check if we deny incoming calls when we use an extension */
865 if (e_ext.noknocking)
867 atemp = apppbx_first;
871 if (!strcmp(atemp->e_ext.number, e_ext.number))
877 PERROR("EPOINT(%d) noknocking and currently a call\n", ea_endpoint->ep_serial);
878 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYSPE_ join, port */
879 return; /* must exit here */
882 /* FALL THROUGH !!!! */
883 case INFO_ITYPE_VBOX:
884 /* get dialed extension's info */
885 // SCPY(exten, e_dialinginfo.id);
886 // if (strchr(exten, ','))
887 // *strchr(exten, ',') = '\0';
888 // if (!read_extension(&e_ext, exten))
889 if (!read_extension(&e_ext, e_dialinginfo.id))
891 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) extension %s not configured\n", ea_endpoint->ep_serial, e_dialinginfo.id);
892 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
893 return; /* must exit here */
896 if (e_dialinginfo.itype == INFO_ITYPE_VBOX)
898 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing directly to VBOX\n", ea_endpoint->ep_serial);
903 /* string from unconditional call forward (cfu) */
907 /* present to forwarded party */
908 if (e_ext.anon_ignore && e_callerinfo.id[0])
910 e_callerinfo.present = INFO_PRESENT_ALLOWED;
912 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
916 /* string from busy call forward (cfb) */
920 class EndpointAppPBX *checkapp = apppbx_first;
923 if (checkapp != this) /* any other endpoint except our own */
925 if (!strcmp(checkapp->e_ext.number, e_ext.number))
927 /* present to forwarded party */
928 if (e_ext.anon_ignore && e_callerinfo.id[0])
930 e_callerinfo.present = INFO_PRESENT_ALLOWED;
932 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
936 checkapp = checkapp->next;
940 /* string from no-response call forward (cfnr) */
944 /* when cfnr is done, out_setup() will setup the call */
947 /* present to forwarded party */
948 if (e_ext.anon_ignore && e_callerinfo.id[0])
950 e_callerinfo.present = INFO_PRESENT_ALLOWED;
954 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
956 e_cfnr_release = now + e_ext.cfnr_delay;
957 e_cfnr_call = now + e_ext.cfnr_delay + 1; /* call one second after release */
958 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);
962 /* call to all internal interfaces */
963 p = e_ext.interfaces;
964 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) generating multiple joins for extension %s to interfaces %s\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
968 while(*p!=',' && *p!='\0')
973 /* found interface */
974 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
975 /* hunt for mISDNport and create Port */
976 mISDNport = hunt_port(ifname, &channel);
979 trace_header("INTERFACE (not found or busy)", DIRECTION_NONE);
980 add_trace("interface", NULL, "%s", ifname);
984 /* creating INTERNAL port */
985 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
986 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force);
988 FATAL("No memory for DSS1 Port instance\n");
989 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
990 memset(&dialinginfo, 0, sizeof(dialinginfo));
991 SCPY(dialinginfo.id, e_dialinginfo.id);
992 dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
993 dialinginfo.ntype = e_dialinginfo.ntype;
994 /* create port_list relation */
995 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
998 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1000 goto check_anycall_intern;
1002 /* directory.list */
1003 if (e_callerinfo.id[0] && e_ext.display_name)
1005 dirname = parse_directory(e_callerinfo.id, e_callerinfo.ntype);
1007 SCPY(e_callerinfo.name, dirname);
1009 // dss1 = (class Pdss1 *)port;
1011 //printf("INTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1012 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1013 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1014 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1015 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1016 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1017 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1018 //terminal if (e_dialinginfo.id)
1019 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1020 /* handle restricted caller ids */
1021 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);
1022 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);
1023 /* display callerid if desired for extension */
1024 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));
1025 //printf("\n\ndisplay = %s\n\n\n",message->param.setup.callerinfo.display);
1026 /* use cnip, if enabld */
1027 // if (!e_ext.centrex)
1028 // message->param.setup.callerinfo.name[0] = '\0';
1029 /* screen clip if prefix is required */
1030 if (message->param.setup.callerinfo.id[0] && e_ext.clip_prefix[0])
1032 SCPY(message->param.setup.callerinfo.id, e_ext.clip_prefix);
1033 SCAT(message->param.setup.callerinfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype, options.national, options.international));
1034 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1036 /* use internal caller id */
1037 if (e_callerinfo.extension[0] && (message->param.setup.callerinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
1039 SCPY(message->param.setup.callerinfo.id, e_callerinfo.extension);
1040 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1042 message_put(message);
1043 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1047 /* string from parallel call forward (cfp) */
1051 if (e_ext.anon_ignore && e_callerinfo.id[0])
1053 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1057 vbox_only: /* entry point for answering machine only */
1058 cfu_only: /* entry point for cfu */
1059 cfb_only: /* entry point for cfb */
1060 cfnr_only: /* entry point for cfnr */
1061 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call extension %s for external destiantion(s) '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
1066 /* only if vbox should be dialed, and terminal is given */
1067 if (!strcmp(p, "vbox") && e_ext.number[0])
1069 /* go to the end of p */
1072 /* answering vbox call */
1073 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) answering machine\n", ea_endpoint->ep_serial);
1075 if (!(port = new VBoxPort(PORT_TYPE_VBOX_OUT, &port_settings)))
1076 FATAL("No memory for VBOX Port instance\n");
1077 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocated port %s\n", ea_endpoint->ep_serial, port->p_name);
1078 UCPY(cfp, e_ext.number); /* cfp or any other direct forward/vbox */
1082 while(*p!=',' && *p!='\0')
1087 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cfp external %s\n", ea_endpoint->ep_serial, cfp);
1088 /* hunt for mISDNport and create Port */
1089 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1092 /* creating EXTERNAL port*/
1093 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1094 if (!(port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force)))
1095 FATAL("No memory for DSS1 Port instance\n");
1096 earlyb = mISDNport->earlyb;
1100 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1101 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1107 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port found or created, which is idle.\n", ea_endpoint->ep_serial);
1108 goto check_anycall_intern;
1110 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found or created port %s\n", ea_endpoint->ep_serial, port->p_name);
1111 memset(&dialinginfo, 0, sizeof(dialinginfo));
1112 SCPY(dialinginfo.id, cfp);
1113 dialinginfo.itype = INFO_ITYPE_ISDN;
1114 dialinginfo.ntype = e_dialinginfo.ntype;
1115 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
1118 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1120 goto check_anycall_intern;
1122 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1123 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1124 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1125 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1126 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1127 /* if clip is hidden */
1128 if (e_ext.clip==CLIP_HIDE && port->p_type!=PORT_TYPE_VBOX_OUT)
1130 SCPY(message->param.setup.callerinfo.id, e_ext.callerid);
1131 SCPY(message->param.setup.callerinfo.extension, e_ext.number);
1132 message->param.setup.callerinfo.ntype = e_ext.callerid_type;
1133 message->param.setup.callerinfo.present = e_ext.callerid_present;
1135 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1136 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1137 //terminal if (e_dialinginfo.id)
1138 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1139 /* handle restricted caller ids */
1140 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);
1141 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);
1142 /* display callerid if desired for extension */
1143 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));
1144 message_put(message);
1145 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1149 check_anycall_intern:
1150 /* now we have all ports created */
1153 trace_header("INTERFACE (no extension's interface)", DIRECTION_NONE);
1155 if (!ea_endpoint->ep_join_id)
1157 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1158 return; /* must exit here */
1162 /* *********************** external call */
1164 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id);
1165 /* call to extenal interfaces */
1166 p = e_dialinginfo.id;
1170 while(*p!=',' && *p!='\0')
1171 SCCAT(number, *p++);
1175 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to number '%s' interface '%s'\n", ea_endpoint->ep_serial, number, e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1176 /* hunt for mISDNport and create Port */
1177 /* hunt for mISDNport and create Port */
1178 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1181 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1182 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1184 goto check_anycall_extern;
1186 /* creating EXTERNAL port*/
1187 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1188 if (!(port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force)))
1189 FATAL("No memory for DSS1 Port instance\n");
1190 earlyb = mISDNport->earlyb;
1191 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
1192 memset(&dialinginfo, 0, sizeof(dialinginfo));
1193 SCPY(dialinginfo.id, number);
1194 dialinginfo.itype = INFO_ITYPE_ISDN;
1195 dialinginfo.ntype = e_dialinginfo.ntype;
1196 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
1199 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1201 goto check_anycall_extern;
1203 // dss1 = (class Pdss1 *)port;
1204 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1205 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1206 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1207 SCPY(message->param.setup.dialinginfo.id, number);
1208 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1209 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1210 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1211 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1212 //terminal if (e_dialinginfo.id)
1213 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1214 /* handle restricted caller ids */
1215 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);
1216 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);
1217 /* display callerid if desired for extension */
1218 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));
1219 message_put(message);
1220 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1224 check_anycall_extern:
1225 /* now we have all ports created */
1228 trace_header("INTERFACE (no free ports found)", DIRECTION_NONE);
1230 if (!ea_endpoint->ep_join_id)
1232 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1233 return; /* must exit here */
1241 /* handler for endpoint
1245 int EndpointAppPBX::handler(void)
1247 if (e_crypt_state!=CM_ST_NULL)
1252 /* process answering machine (play) handling */
1255 if (e_action->index == ACTION_VBOX_PLAY)
1258 /* process action timeout */
1259 if (e_action_timeout)
1260 if (now_d >= e_action_timeout)
1262 if (e_state!=EPOINT_STATE_CONNECT)
1265 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current action timed out.\n", ea_endpoint->ep_serial);
1266 e_multipoint_cause = 0;
1267 e_multipoint_location = 0;
1268 new_state(EPOINT_STATE_IN_OVERLAP);
1271 return(1); /* we must exit, because our endpoint might be gone */
1273 e_action_timeout = 0;
1276 /* process action timeout */
1277 if (e_match_timeout)
1278 if (now_d >= e_match_timeout)
1281 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we got a match timeout.\n", ea_endpoint->ep_serial);
1283 return(1); /* we must exit, because our endpoint might be gone */
1288 /* process redialing (epoint redials to port) */
1291 if (now_d >= e_redial)
1294 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial.\n", ea_endpoint->ep_serial);
1296 new_state(EPOINT_STATE_OUT_SETUP);
1297 /* call special setup routine */
1304 /* process powerdialing (epoint redials to epoint) */
1305 if (e_powerdialing > 0)
1307 if (now_d >= e_powerdialing)
1309 e_powerdialing = -1; /* leave power dialing on */
1310 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial of powerdial.\n", ea_endpoint->ep_serial);
1313 e_ruleset = ruleset_main;
1315 e_rule = e_ruleset->rule_first;
1317 new_state(EPOINT_STATE_IN_OVERLAP);
1323 /* process call forward no response */
1326 struct port_list *portlist;
1327 struct lcr_msg *message;
1329 if (now >= e_cfnr_release)
1331 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-no-response time has expired, hanging up.\n", ea_endpoint->ep_serial);
1334 /* release all ports */
1335 while((portlist = ea_endpoint->ep_portlist))
1337 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1338 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
1339 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1340 message_put(message);
1341 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1342 ea_endpoint->free_portlist(portlist);
1345 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1346 message->param.audiopath = 0;
1347 message_put(message);
1348 /* indicate no patterns */
1349 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1350 message_put(message);
1351 /* set setup state, since we have no response from the new join */
1352 new_state(EPOINT_STATE_OUT_SETUP);
1357 if (now >= e_cfnr_call)
1359 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-busy time has expired, calling the forwarded number: %s.\n", ea_endpoint->ep_serial, e_ext.cfnr);
1365 /* handle connection to user */
1366 if (e_state == EPOINT_STATE_IDLE)
1368 /* epoint is idle, check callback */
1370 if (now_d >= e_callback)
1372 e_callback = 0; /* done with callback */
1373 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting callback.\n", ea_endpoint->ep_serial);
1374 new_state(EPOINT_STATE_OUT_SETUP);
1380 /* check for password timeout */
1382 if (e_action->index==ACTION_PASSWORD || e_action->index==ACTION_PASSWORD_WRITE)
1384 struct port_list *portlist;
1386 if (now >= e_password_timeout)
1388 e_ruleset = ruleset_main;
1390 e_rule = e_ruleset->rule_first;
1392 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) password timeout %s\n", ea_endpoint->ep_serial, e_extdialing);
1393 trace_header("PASSWORD timeout", DIRECTION_NONE);
1395 e_connectedmode = 0;
1397 new_state(EPOINT_STATE_OUT_DISCONNECT);
1398 portlist = ea_endpoint->ep_portlist;
1401 message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
1402 set_tone(portlist, "cause_10");
1412 /* doing a hookflash */
1413 void EndpointAppPBX::hookflash(void)
1417 /* be sure that we are active */
1419 e_tx_state = NOTIFY_STATE_ACTIVE;
1421 trace_header("HOOKFLASH DTMF", DIRECTION_NONE);
1423 if (ea_endpoint->ep_use > 1)
1425 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot hooflash while child process is running.\n", ea_endpoint->ep_serial);
1428 /* dialtone after pressing the hash key */
1429 process_hangup(e_join_cause, e_join_location);
1430 e_multipoint_cause = 0;
1431 e_multipoint_location = 0;
1432 port = find_port_id(ea_endpoint->ep_portlist->port_id);
1435 port->set_echotest(0);
1437 if (ea_endpoint->ep_join_id)
1439 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1441 e_ruleset = ruleset_main;
1443 e_rule = e_ruleset->rule_first;
1445 new_state(EPOINT_STATE_IN_OVERLAP);
1446 e_connectedmode = 1;
1447 SCPY(e_dialinginfo.id, e_ext.prefix);
1448 e_extdialing = e_dialinginfo.id;
1450 if (e_dialinginfo.id[0])
1452 set_tone(ea_endpoint->ep_portlist, "dialing");
1456 set_tone(ea_endpoint->ep_portlist, "dialpbx");
1463 /* messages from port
1465 /* port MESSAGE_SETUP */
1466 void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, union parameter *param)
1468 struct lcr_msg *message;
1470 int writeext; /* flags need to write extension after modification */
1472 struct interface *interface;
1474 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1476 portlist->port_type = param->setup.port_type;
1477 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
1478 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
1479 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
1480 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
1481 // e_dtmf = param->setup.dtmf;
1482 /* screen incoming caller id */
1483 interface = interface_first;
1486 if (!strcmp(e_callerinfo.interface, interface->name))
1490 interface = interface->next;
1493 do_screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface);
1495 /* process extension */
1496 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1498 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is extension\n", ea_endpoint->ep_serial);
1499 /* port makes call from extension */
1500 SCPY(e_callerinfo.extension, e_callerinfo.id);
1501 SCPY(e_ext.number, e_callerinfo.extension);
1502 SCPY(e_extension_interface, e_callerinfo.interface);
1505 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is external or voip\n", ea_endpoint->ep_serial);
1508 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1510 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1512 /* get extension's info about caller */
1513 if (!read_extension(&e_ext, e_ext.number))
1515 /* extension doesn't exist */
1516 trace_header("EXTENSION (not created)", DIRECTION_IN);
1517 add_trace("extension", NULL, "%s", e_ext.number);
1519 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
1520 new_state(EPOINT_STATE_OUT_DISCONNECT);
1521 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
1522 e_ext.number[0] = '\0'; /* no terminal */
1527 /* put prefix (next) in front of e_dialinginfo.id */
1530 SPRINT(buffer, "%s%s", e_ext.next, e_dialinginfo.id);
1531 SCPY(e_dialinginfo.id, buffer);
1532 e_ext.next[0] = '\0';
1534 } else if (e_ext.prefix[0])
1536 SPRINT(buffer, "%s%s", e_ext.prefix, e_dialinginfo.id);
1537 SCPY(e_dialinginfo.id, buffer);
1540 /* screen caller id by extension's config */
1541 e_callerinfo.screen = INFO_SCREEN_NETWORK;
1543 SCPY(e_callerinfo.name, e_ext.name);
1544 /* use caller id (or if exist: id_next_call) for this call */
1545 if (e_ext.id_next_call_present >= 0)
1547 SCPY(e_callerinfo.id, e_ext.id_next_call);
1548 /* if we restrict the pesentation */
1549 if (e_ext.id_next_call_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1550 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1551 else e_callerinfo.present = e_ext.id_next_call_present;
1552 e_callerinfo.ntype = e_ext.id_next_call_type;
1553 e_ext.id_next_call_present = -1;
1557 SCPY(e_callerinfo.id, e_ext.callerid);
1558 /* if we restrict the pesentation */
1559 if (e_ext.callerid_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1560 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1561 else e_callerinfo.present = e_ext.callerid_present;
1562 e_callerinfo.ntype = e_ext.callerid_type;
1565 /* extension is written */
1567 write_extension(&e_ext, e_ext.number);
1569 /* set volume of rx and tx */
1570 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1571 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
1573 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
1574 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
1575 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
1576 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
1577 message_put(message);
1580 /* start recording if enabled */
1581 if (e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO))
1583 /* check if we are a terminal */
1584 if (e_ext.number[0] == '\0')
1585 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
1588 port = find_port_id(portlist->port_id);
1590 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
1595 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from external port\n", ea_endpoint->ep_serial);
1596 /* no terminal identification */
1597 e_ext.number[0] = '\0';
1598 e_extension_interface[0] = '\0';
1599 memset(&e_ext, 0, sizeof(e_ext));
1600 e_ext.rights = 4; /* right to dial internat */
1604 e_ruleset = ruleset_main;
1606 e_rule = e_ruleset->rule_first;
1608 e_extdialing = e_dialinginfo.id;
1609 new_state(EPOINT_STATE_IN_SETUP);
1610 if (e_dialinginfo.id[0])
1612 set_tone(portlist, "dialing");
1615 if (e_ext.number[0])
1616 set_tone(portlist, "dialpbx");
1618 set_tone(portlist, "dialtone");
1621 if (e_state == EPOINT_STATE_IN_SETUP)
1623 /* request MORE info, if not already at higher state */
1624 new_state(EPOINT_STATE_IN_OVERLAP);
1625 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_OVERLAP);
1626 message_put(message);
1627 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1631 /* port MESSAGE_INFORMATION */
1632 void EndpointAppPBX::port_information(struct port_list *portlist, int message_type, union parameter *param)
1634 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1638 /* turn off dtmf detection, in case dtmf is sent with keypad information */
1641 trace_header("DTMF (disabling due to keypad)", DIRECTION_IN);
1646 /* if vbox_play is done, the information are just used as they come */
1648 if (e_action->index == ACTION_VBOX_PLAY)
1650 /* concat dialing string */
1651 SCAT(e_dialinginfo.id, param->information.id);
1656 /* keypad when disconnect but in connected mode */
1657 if (e_state==EPOINT_STATE_OUT_DISCONNECT && e_connectedmode)
1659 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received after disconnect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1660 /* processing keypad function */
1661 if (param->information.id[0] == '0')
1668 /* keypad when connected */
1669 if (e_state == EPOINT_STATE_CONNECT)
1671 if (e_ext.keypad || e_enablekeypad)
1673 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1674 /* processing keypad function */
1675 if (param->information.id[0] == '0')
1679 if (param->information.id[0])
1680 keypad_function(param->information.id[0]);
1683 if (e_ext.number[0])
1684 trace_header("KEYPAD (not enabled by extension's settings)", DIRECTION_IN);
1686 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1691 if (e_state != EPOINT_STATE_IN_OVERLAP)
1693 if (e_ext.number[0])
1694 trace_header("KEYPAD (ignored, not connected and not dialing)", DIRECTION_IN);
1696 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1700 if (!param->information.id[0])
1702 if (e_dialinginfo.id[0]=='\0' && !e_action)
1704 set_tone(portlist, "dialing");
1707 if (e_action->index==ACTION_OUTDIAL
1708 || e_action->index==ACTION_EXTERNAL
1709 || e_action->index==ACTION_REMOTE)
1712 set_tone(portlist, "dialing");
1713 else if (!e_extdialing[0])
1714 set_tone(portlist, "dialing");
1716 /* concat dialing string */
1717 SCAT(e_dialinginfo.id, param->information.id);
1721 /* port MESSAGE_DTMF */
1722 void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
1724 /* only if dtmf detection is enabled */
1727 trace_header("DTMF (disabled)", DIRECTION_IN);
1731 trace_header("DTMF", DIRECTION_IN);
1732 add_trace("digit", NULL, "%c", param->dtmf);
1736 NOTE: vbox is now handled due to overlap state
1737 /* if vbox_play is done, the dtmf digits are just used as they come */
1739 if (e_action->index == ACTION_VBOX_PLAY)
1741 /* concat dialing string */
1742 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id))
1744 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1745 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1748 /* continue to process *X# sequences */
1752 /* check for *X# sequence */
1753 if (e_state == EPOINT_STATE_CONNECT)
1755 if (e_dtmf_time+3 < now)
1757 /* the last digit was too far in the past to be a sequence */
1758 if (param->dtmf == '*')
1759 /* only start is allowed in the sequence */
1765 /* we have a sequence of digits, see what we got */
1766 if (param->dtmf == '*')
1768 else if (param->dtmf>='0' && param->dtmf<='9')
1770 /* we need to have a star before we receive the digit of the sequence */
1771 if (e_dtmf_last == '*')
1772 e_dtmf_last = param->dtmf;
1773 } else if (param->dtmf == '#')
1776 if (e_dtmf_last>='0' && e_dtmf_last<='9')
1778 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf sequence *%c# detected.\n", ea_endpoint->ep_serial, e_dtmf_last);
1779 if (e_dtmf_last == '0')
1784 /* processing keypad function */
1786 keypad_function(e_dtmf_last);
1792 /* set last time of dtmf */
1797 /* check for ## hookflash during dialing */
1799 if (e_action->index==ACTION_PASSWORD
1800 || e_action->index==ACTION_PASSWORD_WRITE)
1802 if (param->dtmf=='#') /* current digit is '#' */
1804 if (e_state==EPOINT_STATE_IN_DISCONNECT
1805 || (e_state!=EPOINT_STATE_CONNECT && e_dtmf_time+3>=now && e_dtmf_last=='#')) /* when disconnected, just #. when dialing, ##. */
1822 /* dialing using dtmf digit */
1823 if (e_state==EPOINT_STATE_IN_OVERLAP)// && e_state==e_connectedmode)
1825 if (e_dialinginfo.id[0]=='\0' && !e_action)
1827 set_tone(portlist, "dialing");
1829 /* concat dialing string */
1830 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id))
1832 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1833 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1839 /* port MESSAGE_CRYPT */
1840 void EndpointAppPBX::port_crypt(struct port_list *portlist, int message_type, union parameter *param)
1842 /* send crypt response to cryptman */
1843 if (param->crypt.type == CR_MESSAGE_IND)
1844 cryptman_msg2man(param->crypt.data, param->crypt.len);
1846 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
1849 /* port MESSAGE_OVERLAP */
1850 void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, union parameter *param)
1852 struct lcr_msg *message;
1854 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1856 /* signal to call tool */
1857 admin_call_response(e_adminid, ADMIN_CALL_SETUP_ACK, "", 0, 0, 0);
1859 if (e_dialing_queue[0] && portlist)
1861 /* send what we have not dialed yet, because we had no setup complete */
1862 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing pending digits: '%s'\n", ea_endpoint->ep_serial, e_dialing_queue);
1863 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
1864 SCPY(message->param.information.id, e_dialing_queue);
1865 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
1866 message_put(message);
1867 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
1868 e_dialing_queue[0] = '\0';
1870 /* check if pattern is available */
1871 if (!ea_endpoint->ep_portlist->next && portlist->early_b) /* one port_list relation and tones available */
1873 /* indicate patterns */
1874 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1875 message_put(message);
1877 /* connect audio, if not already */
1878 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1879 message->param.audiopath = 1;
1880 message_put(message);
1883 /* indicate no patterns */
1884 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1885 message_put(message);
1887 /* disconnect audio, if not already */
1888 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1889 message->param.audiopath = 0;
1890 message_put(message);
1892 new_state(EPOINT_STATE_OUT_OVERLAP);
1893 /* if we are in a join */
1894 if (ea_endpoint->ep_join_id)
1896 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1897 memcpy(&message->param, param, sizeof(union parameter));
1898 message_put(message);
1902 /* port MESSAGE_PROCEEDING */
1903 void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_type, union parameter *param)
1905 struct lcr_msg *message;
1907 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1909 /* signal to call tool */
1910 admin_call_response(e_adminid, ADMIN_CALL_PROCEEDING, "", 0, 0, 0);
1912 e_state = EPOINT_STATE_OUT_PROCEEDING;
1913 /* check if pattern is availatle */
1914 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
1916 /* indicate patterns */
1917 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1918 message_put(message);
1920 /* connect audio, if not already */
1921 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1922 message->param.audiopath = 1;
1923 message_put(message);
1926 /* indicate no patterns */
1927 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1928 message_put(message);
1930 /* disconnect audio, if not already */
1931 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1932 message->param.audiopath = 0;
1933 message_put(message);
1935 /* if we are in a call */
1936 if (ea_endpoint->ep_join_id)
1938 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1939 memcpy(&message->param, param, sizeof(union parameter));
1940 message_put(message);
1944 /* port MESSAGE_ALERTING */
1945 void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type, union parameter *param)
1947 struct lcr_msg *message;
1949 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1951 /* signal to call tool */
1952 admin_call_response(e_adminid, ADMIN_CALL_ALERTING, "", 0, 0, 0);
1955 // set_tone(portlist, "hold");
1957 new_state(EPOINT_STATE_OUT_ALERTING);
1958 /* check if pattern is available */
1959 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
1961 /* indicate patterns */
1962 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1963 message_put(message);
1965 /* connect audio, if not already */
1966 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1967 message->param.audiopath = 1;
1968 message_put(message);
1971 /* indicate no patterns */
1972 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1973 message_put(message);
1975 /* disconnect audio, if not already */
1976 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1977 message->param.audiopath = 0;
1978 message_put(message);
1980 /* if we are in a call */
1981 if (ea_endpoint->ep_join_id)
1983 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1984 memcpy(&message->param, param, sizeof(union parameter));
1985 message_put(message);
1989 /* port MESSAGE_CONNECT */
1990 void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, union parameter *param)
1992 struct lcr_msg *message;
1994 unsigned int port_id = portlist->port_id;
1995 struct port_list *tportlist;
1997 struct interface *interface;
1999 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2001 /* signal to call tool */
2002 admin_call_response(e_adminid, ADMIN_CALL_CONNECT, numberrize_callerinfo(param->connectinfo.id,param->connectinfo.ntype, options.national, options.international), 0, 0, 0);
2004 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_connectinfo));
2005 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (start)\n", ea_endpoint->ep_serial);
2006 while(ea_endpoint->ep_portlist->next) /* as long as we have at least two ports */
2008 tportlist = ea_endpoint->ep_portlist;
2009 if (tportlist->port_id == port_id) /* if the first portlist is the calling one, the second must be a different one */
2010 tportlist = tportlist->next;
2011 if (tportlist->port_id == port_id)
2012 FATAL("EPOINT(%d) this should not happen since the portlist list must not have two links to the same port - exitting.\n");
2013 message = message_create(ea_endpoint->ep_serial, tportlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2014 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
2015 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2016 message_put(message);
2017 logmessage(message->type, &message->param, tportlist->port_id, DIRECTION_OUT);
2018 ea_endpoint->free_portlist(tportlist);
2020 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (end)\n", ea_endpoint->ep_serial);
2024 /* screen incoming connected id */
2025 interface = interface_first;
2028 if (!strcmp(e_connectinfo.interface, interface->name))
2032 interface = interface->next;
2035 do_screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface);
2037 /* screen connected name */
2039 SCPY(e_connectinfo.name, e_ext.name);
2041 /* add internal id to colp */
2042 SCPY(e_connectinfo.extension, e_ext.number);
2044 /* we store the connected port number */
2045 SCPY(e_extension_interface, e_connectinfo.interface);
2047 /* for internal and am calls, we get the extension's id */
2048 if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE)
2050 SCPY(e_connectinfo.id, e_ext.callerid);
2051 SCPY(e_connectinfo.extension, e_ext.number);
2052 e_connectinfo.itype = INFO_ITYPE_ISDN_EXTENSION;
2053 e_connectinfo.ntype = e_ext.callerid_type;
2054 e_connectinfo.present = e_ext.callerid_present;
2056 if (portlist->port_type==PORT_TYPE_VBOX_OUT)
2058 e_connectinfo.itype = INFO_ITYPE_VBOX;
2059 e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2062 new_state(EPOINT_STATE_CONNECT);
2064 /* set volume of rx and tx */
2065 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
2067 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2068 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2069 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
2070 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
2071 message_put(message);
2074 e_cfnr_call = e_cfnr_release = 0;
2075 if (e_ext.number[0])
2076 e_dtmf = 1; /* allow dtmf */
2079 /* other calls with no caller id (or not available for the extension) and force colp */
2080 if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE)
2082 e_connectinfo.present = INFO_PRESENT_NOTAVAIL;
2083 if (portlist->port_type==PORT_TYPE_DSS1_TE_OUT || portlist->port_type==PORT_TYPE_DSS1_NT_OUT) /* external extension answered */
2085 port = find_port_id(portlist->port_id);
2088 SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.id, &e_connectinfo.ntype, options.national, options.international));
2089 e_connectinfo.present = INFO_PRESENT_ALLOWED;
2094 /* send connect to join */
2095 if (ea_endpoint->ep_join_id)
2097 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2098 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
2099 message_put(message);
2101 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2102 message->param.audiopath = 1;
2103 message_put(message);
2104 } else if (!e_adminid)
2107 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have a callback, so we create a call with cbcaller: \"%s\".\n", ea_endpoint->ep_serial, e_cbcaller);
2108 SCPY(e_ext.number, e_cbcaller);
2109 new_state(EPOINT_STATE_IN_OVERLAP);
2110 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) callback from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2112 /* get extension's info about terminal */
2113 if (!read_extension(&e_ext, e_ext.number))
2115 /* extension doesn't exist */
2116 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2117 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
2118 new_state(EPOINT_STATE_OUT_DISCONNECT);
2119 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
2123 /* put prefix in front of e_cbdialing */
2124 SPRINT(buffer, "%s%s", e_ext.prefix, e_cbdialing);
2125 SCPY(e_dialinginfo.id, buffer);
2126 e_dialinginfo.itype = INFO_ITYPE_ISDN;
2127 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
2129 /* use caller id (or if exist: id_next_call) for this call */
2130 e_callerinfo.screen = INFO_SCREEN_NETWORK;
2131 SCPY(e_callerinfo.extension, e_ext.number);
2132 if (e_ext.id_next_call_present >= 0)
2134 SCPY(e_callerinfo.id, e_ext.id_next_call);
2135 e_callerinfo.present = e_ext.id_next_call_present;
2136 e_callerinfo.ntype = e_ext.id_next_call_type;
2137 e_ext.id_next_call_present = -1;
2138 /* extension is written */
2139 write_extension(&e_ext, e_ext.number);
2142 SCPY(e_callerinfo.id, e_ext.callerid);
2143 e_callerinfo.present = e_ext.callerid_present;
2144 e_callerinfo.ntype = e_ext.callerid_type;
2147 e_connectedmode = 1; /* dtmf-hangup & disconnect prevention */
2150 /* check if caller id is NOT authenticated */
2151 if (!parse_callbackauth(e_ext.number, &e_callbackinfo))
2153 /* make call state to enter password */
2154 new_state(EPOINT_STATE_IN_OVERLAP);
2155 e_action = &action_password_write;
2156 e_match_timeout = 0;
2157 e_match_to_action = NULL;
2158 e_dialinginfo.id[0] = '\0';
2159 e_extdialing = strchr(e_dialinginfo.id, '\0');
2160 e_password_timeout = now+20;
2164 /* incoming call (callback) */
2165 e_ruleset = ruleset_main;
2167 e_rule = e_ruleset->rule_first;
2169 e_extdialing = e_dialinginfo.id;
2170 if (e_dialinginfo.id[0])
2172 set_tone(portlist, "dialing");
2176 set_tone(portlist, "dialpbx");
2179 } else /* testcall */
2181 set_tone(portlist, "hold");
2184 /* start recording if enabled, not when answering machine answers */
2185 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))
2187 /* check if we are a terminal */
2188 if (e_ext.number[0] == '\0')
2189 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
2192 port = find_port_id(portlist->port_id);
2194 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
2199 /* port MESSAGE_DISCONNECT MESSAGE_RELEASE */
2200 void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
2202 struct lcr_msg *message;
2204 unsigned int port_id = portlist->port_id;
2208 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2210 /* signal to call tool */
2211 admin_call_response(e_adminid, (message_type==MESSAGE_DISCONNECT)?ADMIN_CALL_DISCONNECT:ADMIN_CALL_RELEASE, "", param->disconnectinfo.cause, param->disconnectinfo.location, 0);
2213 //#warning does this work? only disconnect when incoming port hat not already disconnected yet?
2214 if (e_state==EPOINT_STATE_IN_DISCONNECT && message_type!=MESSAGE_RELEASE)// || e_state==EPOINT_STATE_OUT_DISCONNECT || e_state==EPOINT_STATE_IDLE)
2216 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are already disconnected.\n", ea_endpoint->ep_serial);
2221 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);
2222 collect_cause(&e_multipoint_cause, &e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location);
2223 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new multipoint cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location);
2225 /* check if we have more than one portlist relation and we just ignore the disconnect */
2226 if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist->next)
2228 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the disconnect was from a multipoint call. we just release that relation.\n", ea_endpoint->ep_serial);
2229 portlist = ea_endpoint->ep_portlist;
2232 if (portlist->port_id == port_id)
2234 portlist = portlist->next;
2237 FATAL("EPOINT(%d) no portlist related to the calling port.\n", ea_endpoint->ep_serial);
2238 if (message_type != MESSAGE_RELEASE)
2240 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2241 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2242 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2243 message_put(message);
2244 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2246 ea_endpoint->free_portlist(portlist);
2247 return; /* one relation removed */
2249 if (e_state == EPOINT_STATE_CONNECT)
2251 /* use cause from port after connect */
2252 cause = param->disconnectinfo.cause;
2253 location = param->disconnectinfo.location;
2256 /* use multipoint cause if no connect yet */
2257 if (e_multipoint_cause)
2259 cause = e_multipoint_cause;
2260 location = e_multipoint_location;
2263 cause = CAUSE_NOUSER;
2264 location = LOCATION_PRIVATE_LOCAL;
2268 e_cfnr_call = e_cfnr_release = 0;
2270 /* process hangup */
2271 process_hangup(e_join_cause, e_join_location);
2272 e_multipoint_cause = 0;
2273 e_multipoint_location = 0;
2275 if (message_type == MESSAGE_DISCONNECT)
2277 /* tone to disconnected end */
2278 SPRINT(buffer, "cause_%02x", cause);
2279 if (ea_endpoint->ep_portlist)
2280 set_tone(ea_endpoint->ep_portlist, buffer);
2282 new_state(EPOINT_STATE_IN_DISCONNECT);
2285 if (ea_endpoint->ep_join_id)
2287 int haspatterns = 0;
2288 /* check if pattern is available */
2289 if (ea_endpoint->ep_portlist)
2290 if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->early_b)
2291 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
2292 && message_type != MESSAGE_RELEASE) // if we release, we are done
2296 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has patterns.\n", ea_endpoint->ep_serial);
2297 /* indicate patterns */
2298 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2299 message_put(message);
2300 /* connect audio, if not already */
2301 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2302 message->param.audiopath = 1;
2303 message_put(message);
2304 /* send disconnect */
2305 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2306 memcpy(&message->param, param, sizeof(union parameter));
2307 message_put(message);
2308 /* disable encryption if disconnected */
2309 //PERROR("REMOVE ME: state =%d, %d\n", e_crypt_state, e_crypt);
2311 cryptman_message(CI_DISCONNECT_IND, NULL, 0);
2315 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
2318 if (message_type == MESSAGE_RELEASE)
2319 ea_endpoint->free_portlist(portlist);
2320 release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, callcause, portcause */
2321 return; /* must exit here */
2324 /* port MESSAGE_TIMEOUT */
2325 void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type, union parameter *param)
2329 trace_header("TIMEOUT", DIRECTION_IN);
2330 message_type = MESSAGE_DISCONNECT;
2331 switch (param->state)
2333 case PORT_STATE_OUT_SETUP:
2334 case PORT_STATE_OUT_OVERLAP:
2335 add_trace("state", NULL, "outgoing setup/dialing");
2337 /* no user responding */
2338 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2339 return; /* must exit here */
2341 case PORT_STATE_IN_SETUP:
2342 case PORT_STATE_IN_OVERLAP:
2343 add_trace("state", NULL, "incoming setup/dialing");
2344 param->disconnectinfo.cause = CAUSE_INVALID; /* number incomplete */
2345 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2348 case PORT_STATE_OUT_PROCEEDING:
2349 add_trace("state", NULL, "outgoing proceeding");
2351 param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
2352 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2353 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2354 return; /* must exit here */
2356 case PORT_STATE_IN_PROCEEDING:
2357 add_trace("state", NULL, "incoming proceeding");
2358 param->disconnectinfo.cause = CAUSE_NOUSER;
2359 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL; /* no user responding */
2362 case PORT_STATE_OUT_ALERTING:
2363 add_trace("state", NULL, "outgoing alerting");
2365 param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
2366 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2367 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2368 return; /* must exit here */
2370 case PORT_STATE_CONNECT:
2371 add_trace("state", NULL, "connect");
2373 param->disconnectinfo.cause = CAUSE_NORMAL; /* normal */
2374 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2375 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2376 return; /* must exit here */
2378 case PORT_STATE_IN_ALERTING:
2379 add_trace("state", NULL, "incoming alerting");
2380 param->disconnectinfo.cause = CAUSE_NOANSWER;
2381 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2384 case PORT_STATE_IN_DISCONNECT:
2385 case PORT_STATE_OUT_DISCONNECT:
2386 add_trace("state", NULL, "disconnect");
2388 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
2389 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2390 return; /* must exit here */
2393 param->disconnectinfo.cause = 31; /* normal unspecified */
2394 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2397 /* release call, disconnect isdn */
2399 new_state(EPOINT_STATE_OUT_DISCONNECT);
2400 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2401 SCPY(e_tone, cause);
2404 set_tone(portlist, cause);
2405 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2406 portlist = portlist->next;
2408 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
2411 /* port MESSAGE_NOTIFY */
2412 void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, union parameter *param)
2414 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2416 struct lcr_msg *message;
2420 /* signal to call tool */
2421 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);
2422 if (param->notifyinfo.notify)
2424 e_rx_state = track_notify(e_rx_state, param->notifyinfo.notify);
2427 /* if we get notification from stack, local shows if we disabled/enabled audio stream */
2428 if (param->notifyinfo.local) switch(param->notifyinfo.notify)
2430 case INFO_NOTIFY_REMOTE_HOLD:
2431 case INFO_NOTIFY_USER_SUSPENDED:
2432 /* tell call about it */
2433 if (ea_endpoint->ep_join_id)
2435 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2436 message->param.audiopath = 0;
2437 message_put(message);
2441 case INFO_NOTIFY_REMOTE_RETRIEVAL:
2442 case INFO_NOTIFY_USER_RESUMED:
2443 /* set volume of rx and tx */
2444 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
2445 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
2448 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2449 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2450 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
2451 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
2452 message_put(message);
2454 /* set current tone */
2456 set_tone(portlist, e_tone);
2457 /* tell call about it */
2458 if (ea_endpoint->ep_join_id)
2460 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2461 message->param.audiopath = 1;
2462 message_put(message);
2467 /* get name of notify */
2468 switch(param->notifyinfo.notify)
2474 logtext = "USER_SUSPENDED";
2477 logtext = "BEARER_SERVICE_CHANGED";
2480 logtext = "USER_RESUMED";
2483 logtext = "CONFERENCE_ESTABLISHED";
2486 logtext = "CONFERENCE_DISCONNECTED";
2489 logtext = "OTHER_PARTY_ADDED";
2492 logtext = "ISOLATED";
2495 logtext = "REATTACHED";
2498 logtext = "OTHER_PARTY_ISOLATED";
2501 logtext = "OTHER_PARTY_REATTACHED";
2504 logtext = "OTHER_PARTY_SPLIT";
2507 logtext = "OTHER_PARTY_DISCONNECTED";
2510 logtext = "CONFERENCE_FLOATING";
2513 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
2516 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
2519 logtext = "CALL_IS_A_WAITING_CALL";
2522 logtext = "DIVERSION_ACTIVATED";
2525 logtext = "RESERVED_CT_1";
2528 logtext = "RESERVED_CT_2";
2531 logtext = "REVERSE_CHARGING";
2534 logtext = "REMOTE_HOLD";
2537 logtext = "REMOTE_RETRIEVAL";
2540 logtext = "CALL_IS_DIVERTING";
2543 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
2548 /* notify call if available */
2549 if (ea_endpoint->ep_join_id)
2551 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOTIFY);
2552 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
2553 message_put(message);
2558 /* port MESSAGE_FACILITY */
2559 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
2561 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2563 struct lcr_msg *message;
2565 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_FACILITY);
2566 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2567 message_put(message);
2570 /* port MESSAGE_SUSPEND */
2571 /* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
2572 void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
2574 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2576 /* epoint is now parked */
2577 ea_endpoint->ep_park = 1;
2578 memcpy(ea_endpoint->ep_park_callid, param->parkinfo.callid, sizeof(ea_endpoint->ep_park_callid));
2579 ea_endpoint->ep_park_len = (param->parkinfo.len>8)?8:param->parkinfo.len;
2581 /* remove port relation */
2582 ea_endpoint->free_portlist(portlist);
2585 /* port MESSAGE_RESUME */
2586 /* NOTE: before resume, the active-notification must be done in order to set call mixer */
2587 void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
2589 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2591 /* epoint is now resumed */
2592 ea_endpoint->ep_park = 0;
2597 /* port sends message to the endpoint
2599 void EndpointAppPBX::ea_message_port(unsigned int port_id, int message_type, union parameter *param)
2601 struct port_list *portlist;
2602 struct lcr_msg *message;
2604 portlist = ea_endpoint->ep_portlist;
2607 if (port_id == portlist->port_id)
2609 portlist = portlist->next;
2613 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);
2617 // PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
2618 switch(message_type)
2620 case MESSAGE_DATA: /* data from port */
2621 /* check if there is a call */
2622 if (!ea_endpoint->ep_join_id)
2624 /* continue if only one portlist */
2625 if (ea_endpoint->ep_portlist->next != NULL)
2627 /* forward message */
2628 message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2631 case MESSAGE_TONE_EOF: /* tone is end of file */
2632 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
2635 if (e_action->index == ACTION_VBOX_PLAY)
2639 if (e_action->index == ACTION_EFI)
2646 case MESSAGE_TONE_COUNTER: /* counter info received */
2647 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);
2649 if (e_action->index == ACTION_VBOX_PLAY)
2651 e_vbox_counter = param->counter.current;
2652 if (param->counter.max >= 0)
2653 e_vbox_counter_max = param->counter.max;
2657 /* PORT sends SETUP message */
2659 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call from callerid=%s, dialing=%s\n", ea_endpoint->ep_serial, param->setup.callerinfo.id, param->setup.dialinginfo.id);
2660 if (e_state!=EPOINT_STATE_IDLE)
2662 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
2665 port_setup(portlist, message_type, param);
2668 /* PORT sends INFORMATION message */
2669 case MESSAGE_INFORMATION: /* additional digits received */
2670 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);
2671 port_information(portlist, message_type, param);
2674 /* PORT sends FACILITY message */
2675 case MESSAGE_FACILITY:
2676 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2677 port_facility(portlist, message_type, param);
2680 /* PORT sends DTMF message */
2681 case MESSAGE_DTMF: /* dtmf digits received */
2682 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);
2683 port_dtmf(portlist, message_type, param);
2686 /* PORT sends CRYPT message */
2687 case MESSAGE_CRYPT: /* crypt response received */
2688 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) crypt response=%d\n", ea_endpoint->ep_serial, param->crypt.type);
2689 port_crypt(portlist, message_type, param);
2692 /* PORT sends MORE message */
2693 case MESSAGE_OVERLAP:
2694 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);
2695 if (e_state != EPOINT_STATE_OUT_SETUP)
2697 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);
2700 port_overlap(portlist, message_type, param);
2703 /* PORT sends PROCEEDING message */
2704 case MESSAGE_PROCEEDING: /* port is proceeding */
2705 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);
2706 if (e_state!=EPOINT_STATE_OUT_SETUP
2707 && e_state!=EPOINT_STATE_OUT_OVERLAP)
2709 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);
2712 port_proceeding(portlist, message_type, param);
2715 /* PORT sends ALERTING message */
2716 case MESSAGE_ALERTING:
2717 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);
2718 if (e_state!=EPOINT_STATE_OUT_SETUP
2719 && e_state!=EPOINT_STATE_OUT_OVERLAP
2720 && e_state!=EPOINT_STATE_OUT_PROCEEDING)
2722 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);
2725 port_alerting(portlist, message_type, param);
2728 /* PORT sends CONNECT message */
2729 case MESSAGE_CONNECT:
2730 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);
2731 if (e_state!=EPOINT_STATE_OUT_SETUP
2732 && e_state!=EPOINT_STATE_OUT_OVERLAP
2733 && e_state!=EPOINT_STATE_OUT_PROCEEDING
2734 && e_state!=EPOINT_STATE_OUT_ALERTING)
2736 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
2739 port_connect(portlist, message_type, param);
2742 /* PORT sends DISCONNECT message */
2743 case MESSAGE_DISCONNECT: /* port is disconnected */
2744 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);
2745 port_disconnect_release(portlist, message_type, param);
2748 /* PORT sends a RELEASE message */
2749 case MESSAGE_RELEASE: /* port releases */
2750 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);
2751 /* portlist is release at port_disconnect_release, thanx Paul */
2752 port_disconnect_release(portlist, message_type, param);
2755 /* PORT sends a TIMEOUT message */
2756 case MESSAGE_TIMEOUT:
2757 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);
2758 port_timeout(portlist, message_type, param);
2759 break; /* release */
2761 /* PORT sends a NOTIFY message */
2762 case MESSAGE_NOTIFY:
2763 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);
2764 port_notify(portlist, message_type, param);
2767 /* PORT sends a SUSPEND message */
2768 case MESSAGE_SUSPEND:
2769 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);
2770 port_suspend(portlist, message_type, param);
2771 break; /* suspend */
2773 /* PORT sends a RESUME message */
2774 case MESSAGE_RESUME:
2775 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);
2776 port_resume(portlist, message_type, param);
2780 kann nach dem test gelöscht werden, da eine direkte funktion im join und im mISDN zum austausch der message existiert
2781 /* port assigns bchannel */
2782 case MESSAGE_BCHANNEL: /* bchannel assignment messafe */
2783 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);
2784 /* only one port is expected to be connected to bchannel */
2785 message = message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2786 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_IN);
2792 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);
2795 /* Note: this endpoint may be destroyed, so we MUST return */
2799 /* messages from join
2801 /* join MESSAGE_CRYPT */
2802 void EndpointAppPBX::join_crypt(struct port_list *portlist, int message_type, union parameter *param)
2804 switch(param->crypt.type)
2806 /* message from remote port to "crypt manager" */
2807 case CU_ACTK_REQ: /* activate key-exchange */
2808 case CU_ACTS_REQ: /* activate shared key */
2809 case CU_DACT_REQ: /* deactivate */
2810 case CU_INFO_REQ: /* request last info message */
2811 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2814 /* message from "crypt manager" to user */
2815 case CU_ACTK_CONF: /* key-echange done */
2816 case CU_ACTS_CONF: /* shared key done */
2817 case CU_DACT_CONF: /* deactivated */
2818 case CU_DACT_IND: /* deactivated */
2819 case CU_ERROR_IND: /* receive error message */
2820 case CU_INFO_IND: /* receive info message */
2821 case CU_INFO_CONF: /* receive info message */
2822 encrypt_result(param->crypt.type, (char *)param->crypt.data);
2826 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);
2830 /* join MESSAGE_INFORMATION */
2831 void EndpointAppPBX::join_information(struct port_list *portlist, int message_type, union parameter *param)
2833 struct lcr_msg *message;
2839 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2840 memcpy(&message->param.information, ¶m->information, sizeof(struct dialing_info));
2841 message_put(message);
2842 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2843 portlist = portlist->next;
2847 /* join MESSAGE_FACILITY */
2848 void EndpointAppPBX::join_facility(struct port_list *portlist, int message_type, union parameter *param)
2850 struct lcr_msg *message;
2852 if (!e_ext.facility && e_ext.number[0])
2859 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_FACILITY);
2860 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2861 message_put(message);
2862 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2863 portlist = portlist->next;
2867 /* join MESSAGE_MORE */
2868 void EndpointAppPBX::join_overlap(struct port_list *portlist, int message_type, union parameter *param)
2870 struct lcr_msg *message;
2872 new_state(EPOINT_STATE_IN_OVERLAP);
2875 if (e_join_pattern && e_ext.own_setup)
2877 /* disconnect audio */
2878 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2879 message->param.audiopath = 0;
2880 message_put(message);
2882 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
2884 if (e_dialinginfo.id[0])
2885 set_tone(portlist, "dialing");
2887 set_tone(portlist, "dialtone");
2890 if (e_dialinginfo.id[0])
2892 set_tone(portlist, "dialing");
2895 if (e_ext.number[0])
2896 set_tone(portlist, "dialpbx");
2898 set_tone(portlist, "dialtone");
2902 /* join MESSAGE_PROCEEDING */
2903 void EndpointAppPBX::join_proceeding(struct port_list *portlist, int message_type, union parameter *param)
2905 struct lcr_msg *message;
2907 new_state(EPOINT_STATE_IN_PROCEEDING);
2909 /* own proceeding tone */
2912 /* connect / disconnect audio */
2913 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2914 if (e_ext.own_proceeding)
2915 message->param.audiopath = 0;
2917 message->param.audiopath = 1;
2918 message_put(message);
2920 // UCPY(e_join_tone, "proceeding");
2923 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
2924 message_put(message);
2925 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2927 set_tone(portlist, "proceeding");
2930 /* join MESSAGE_ALERTING */
2931 void EndpointAppPBX::join_alerting(struct port_list *portlist, int message_type, union parameter *param)
2933 struct lcr_msg *message;
2935 new_state(EPOINT_STATE_IN_ALERTING);
2937 /* own alerting tone */
2940 /* connect / disconnect audio */
2941 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2942 if (e_ext.own_alerting)
2943 message->param.audiopath = 0;
2945 message->param.audiopath = 1;
2946 message_put(message);
2950 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
2951 message_put(message);
2952 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2954 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
2956 set_tone(portlist, "ringing");
2959 if (e_ext.number[0])
2960 set_tone(portlist, "ringpbx");
2962 set_tone(portlist, "ringing");
2965 /* join MESSAGE_CONNECT */
2966 void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type, union parameter *param)
2968 struct lcr_msg *message;
2970 new_state(EPOINT_STATE_CONNECT);
2971 // UCPY(e_join_tone, "");
2973 if (e_ext.number[0])
2974 e_dtmf = 1; /* allow dtmf */
2977 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_callerinfo));
2980 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
2981 memcpy(&message->param, param, sizeof(union parameter));
2983 /* screen clip if prefix is required */
2984 if (e_ext.number[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0])
2986 SCPY(message->param.connectinfo.id, e_ext.clip_prefix);
2987 SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype, options.national, options.international));
2988 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2991 /* use internal caller id */
2992 if (e_ext.number[0] && e_connectinfo.extension[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
2994 SCPY(message->param.connectinfo.id, e_connectinfo.extension);
2995 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2998 /* handle restricted caller ids */
2999 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);
3000 /* display callerid if desired for extension */
3001 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));
3003 /* use conp, if enabld */
3004 // if (!e_ext.centrex)
3005 // message->param.connectinfo.name[0] = '\0';
3008 message_put(message);
3009 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3011 set_tone(portlist, NULL);
3013 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3014 message->param.audiopath = 1;
3015 message_put(message);
3019 /* join MESSAGE_DISCONNECT MESSAGE_RELEASE */
3020 void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *param)
3023 struct lcr_msg *message;
3024 struct port_list *portlist = NULL;
3027 /* be sure that we are active */
3029 e_tx_state = NOTIFY_STATE_ACTIVE;
3031 /* we are powerdialing, if e_powerdialing is set and limit is not exceeded if given */
3032 if (e_powerdialing && ((e_powercount+1)<e_powerlimit || e_powerlimit<1))
3034 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
3036 /* set time for power dialing */
3037 e_powerdialing = now_d + e_powerdelay; /* set redial in the future */
3040 /* set redial tone */
3041 if (ea_endpoint->ep_portlist)
3045 set_tone(ea_endpoint->ep_portlist, "redial");
3046 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);
3047 /* send proceeding when powerdialing and still setup (avoid dialing timeout) */
3048 if (e_state==EPOINT_STATE_IN_OVERLAP)
3050 new_state(EPOINT_STATE_IN_PROCEEDING);
3051 if (ea_endpoint->ep_portlist)
3053 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3054 message_put(message);
3055 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3057 /* caused the error, that the first knock sound was not there */
3058 /* set_tone(portlist, "proceeding"); */
3060 /* send display of powerdialing */
3061 if (e_ext.display_dialing)
3063 portlist = ea_endpoint->ep_portlist;
3066 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3068 SPRINT(message->param.notifyinfo.display, "Retry %d of %d", e_powercount, e_powerlimit);
3070 SPRINT(message->param.notifyinfo.display, "Retry %d", e_powercount);
3071 message_put(message);
3072 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3073 portlist = portlist->next;
3082 if ((e_state!=EPOINT_STATE_CONNECT
3083 && e_state!=EPOINT_STATE_OUT_DISCONNECT
3084 && e_state!=EPOINT_STATE_IN_OVERLAP
3085 && e_state!=EPOINT_STATE_IN_PROCEEDING
3086 && e_state!=EPOINT_STATE_IN_ALERTING)
3087 || !ea_endpoint->ep_portlist) /* or no port */
3089 process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
3090 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause); /* RELEASE_TYPE, join, port */
3091 return; /* must exit here */
3096 e_join_cause = param->disconnectinfo.cause;
3097 e_join_location = param->disconnectinfo.location;
3100 /* on release we need the audio again! */
3101 if (message_type == MESSAGE_RELEASE)
3104 ea_endpoint->ep_join_id = 0;
3106 /* disconnect and select tone */
3107 new_state(EPOINT_STATE_OUT_DISCONNECT);
3108 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
3109 /* if own_cause, we must release the join */
3110 if (e_ext.own_cause /* own cause */
3111 || !e_join_pattern) /* no patterns */
3113 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);
3114 if (message_type != MESSAGE_RELEASE)
3115 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
3117 } else /* else we enable audio */
3119 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3120 message->param.audiopath = 1;
3121 message_put(message);
3123 /* send disconnect message */
3124 SCPY(e_tone, cause);
3125 portlist = ea_endpoint->ep_portlist;
3128 set_tone(portlist, cause);
3129 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
3130 portlist = portlist->next;
3134 /* join MESSAGE_SETUP */
3135 void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, union parameter *param)
3137 struct lcr_msg *message;
3138 // struct interface *interface;
3140 /* if we already in setup state, we just update the dialing with new digits */
3141 if (e_state == EPOINT_STATE_OUT_SETUP
3142 || e_state == EPOINT_STATE_OUT_OVERLAP)
3144 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we are in setup state, so we do overlap dialing.\n", ea_endpoint->ep_serial);
3145 /* if digits changed, what we have already dialed */
3146 if (!!strncmp(e_dialinginfo.id,param->setup.dialinginfo.id,strlen(e_dialinginfo.id)))
3148 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);
3149 /* release all ports */
3150 while((portlist = ea_endpoint->ep_portlist))
3152 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
3153 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
3154 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3155 message_put(message);
3156 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3157 ea_endpoint->free_portlist(portlist);
3160 /* disconnect audio */
3161 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3162 message->param.audiopath = 0;
3163 message_put(message);
3165 /* get dialing info */
3166 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3167 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3168 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3169 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3170 new_state(EPOINT_STATE_OUT_OVERLAP);
3173 e_redial = now_d + 1; /* set redial one second in the future */
3176 /* if we have a pending redial, so we just adjust the dialing number */
3179 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);
3180 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3183 if (!ea_endpoint->ep_portlist)
3185 PERROR("ERROR: overlap dialing to a NULL port relation\n");
3187 if (ea_endpoint->ep_portlist->next)
3189 PERROR("ERROR: overlap dialing to a port_list port relation\n");
3191 if (e_state == EPOINT_STATE_OUT_SETUP)
3194 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);
3195 SCAT(e_dialing_queue, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3199 /* get what we have not dialed yet */
3200 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));
3201 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
3202 SCPY(message->param.information.id, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3203 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
3204 message_put(message);
3205 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3207 /* always store what we have dialed or queued */
3208 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3212 if (e_state != EPOINT_STATE_IDLE)
3214 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
3217 /* if an internal extension is dialed, copy that number */
3218 if (param->setup.dialinginfo.itype==INFO_ITYPE_ISDN_EXTENSION || param->setup.dialinginfo.itype==INFO_ITYPE_VBOX)
3219 SCPY(e_ext.number, param->setup.dialinginfo.id);
3220 /* if an internal extension is dialed, get extension's info about caller */
3221 if (e_ext.number[0])
3223 if (!read_extension(&e_ext, e_ext.number))
3225 e_ext.number[0] = '\0';
3226 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the called terminal='%s' is not found in directory tree!\n", ea_endpoint->ep_serial, e_ext.number);
3230 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3231 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3232 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3233 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3235 /* process (voice over) data calls */
3236 if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO)
3238 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) handling data call as audio call: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
3239 memset(&e_capainfo, 0, sizeof(e_capainfo));
3240 e_capainfo.bearer_capa = INFO_BC_AUDIO;
3241 e_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
3242 e_capainfo.bearer_info1 = (options.law=='u')?INFO_INFO1_ULAW:INFO_INFO1_ALAW;
3245 new_state(EPOINT_STATE_OUT_SETUP);
3246 /* call special setup routine */
3250 /* join MESSAGE_mISDNSIGNAL */
3251 void EndpointAppPBX::join_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param)
3253 struct lcr_msg *message;
3257 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
3258 memcpy(&message->param, param, sizeof(union parameter));
3259 message_put(message);
3260 portlist = portlist->next;
3264 /* join MESSAGE_NOTIFY */
3265 void EndpointAppPBX::join_notify(struct port_list *portlist, int message_type, union parameter *param)
3267 struct lcr_msg *message;
3270 if (param->notifyinfo.notify)
3272 new_state = track_notify(e_tx_state, param->notifyinfo.notify);
3273 // /* if notification was generated locally, we turn hold music on/off */
3274 // if (param->notifyinfo.local)
3275 // NOTE: we always assume that we send hold music on suspension of call, because we don't track if audio is available or not (we assume that we always have no audio, to make it easier)
3280 if (new_state!=NOTIFY_STATE_HOLD && new_state!=NOTIFY_STATE_SUSPEND)
3282 if (!strcmp(e_tone, "hold")) // don't interrupt other tones
3286 set_tone(portlist, "");
3287 portlist = portlist->next;
3290 portlist = ea_endpoint->ep_portlist;
3295 if (new_state==NOTIFY_STATE_HOLD || new_state==NOTIFY_STATE_SUSPEND)
3299 set_tone(portlist, "hold");
3300 portlist = portlist->next;
3302 portlist = ea_endpoint->ep_portlist;
3307 /* save new state */
3308 e_tx_state = new_state;
3311 /* notify port(s) about it */
3314 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3315 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
3316 /* handle restricted caller ids */
3317 apply_callerid_restriction(&e_ext, message->param.notifyinfo.id, &message->param.notifyinfo.ntype, &message->param.notifyinfo.present, 0, message->param.notifyinfo.extension, NULL);
3318 /* display callerid if desired for extension */
3319 SCPY(message->param.notifyinfo.display, apply_callerid_display(message->param.notifyinfo.id, message->param.notifyinfo.itype, message->param.notifyinfo.ntype, message->param.notifyinfo.present, 0, message->param.notifyinfo.extension, NULL));
3320 message_put(message);
3321 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3322 portlist = portlist->next;
3326 /* JOIN sends messages to the endpoint
3328 void EndpointAppPBX::ea_message_join(unsigned int join_id, int message_type, union parameter *param)
3330 struct port_list *portlist;
3331 struct lcr_msg *message;
3335 PERROR("EPOINT(%d) error: JOIN == NULL.\n", ea_endpoint->ep_serial);
3339 portlist = ea_endpoint->ep_portlist;
3341 /* send MESSAGE_DATA to port */
3342 if (message_type == MESSAGE_DATA)
3344 if (join_id == ea_endpoint->ep_join_id) // still linked with JOIN
3346 /* skip if no port relation */
3349 /* skip if more than one port relation */
3352 /* forward audio data to port */
3353 message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3358 // PDEBUG(DEBUG_EPOINT, "EPOINT(%d) received message %d for active JOIN (terminal %s, caller id %s state=%d)\n", ea_endpoint->ep_serial, message, e_ext.number, e_callerinfo.id, e_state);
3359 switch(message_type)
3361 /* JOIN SENDS TONE message */
3363 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received tone message: '%d'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->tone.name);
3364 set_tone(portlist, param->tone.name);
3367 /* JOIN SENDS CRYPT message */
3369 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received crypt message: '%d'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->crypt.type);
3370 join_crypt(portlist, message_type, param);
3373 /* JOIN sends INFORMATION message */
3374 case MESSAGE_INFORMATION:
3375 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received more digits: '%s'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->information.id);
3376 join_information(portlist, message_type, param);
3379 /* JOIN sends FACILITY message */
3380 case MESSAGE_FACILITY:
3381 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received facility\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3382 join_facility(portlist, message_type, param);
3385 /* JOIN sends OVERLAP message */
3386 case MESSAGE_OVERLAP:
3387 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received 'more info required'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3388 if (e_state!=EPOINT_STATE_IN_SETUP
3389 && e_state!=EPOINT_STATE_IN_OVERLAP)
3391 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3394 join_overlap(portlist, message_type, param);
3397 /* JOIN sends PROCEEDING message */
3398 case MESSAGE_PROCEEDING:
3399 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s (caller id '%s') received proceeding\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3400 if(e_state!=EPOINT_STATE_IN_OVERLAP)
3402 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3405 join_proceeding(portlist, message_type, param);
3408 /* JOIN sends ALERTING message */
3409 case MESSAGE_ALERTING:
3410 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received alerting\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3411 if (e_state!=EPOINT_STATE_IN_OVERLAP
3412 && e_state!=EPOINT_STATE_IN_PROCEEDING)
3414 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state.\n", ea_endpoint->ep_serial);
3417 join_alerting(portlist, message_type, param);
3420 /* JOIN sends CONNECT message */
3421 case MESSAGE_CONNECT:
3422 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received connect\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3423 if (e_state!=EPOINT_STATE_IN_OVERLAP
3424 && e_state!=EPOINT_STATE_IN_PROCEEDING
3425 && e_state!=EPOINT_STATE_IN_ALERTING)
3427 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
3430 join_connect(portlist, message_type, param);
3433 /* JOIN sends DISCONNECT/RELEASE message */
3434 case MESSAGE_DISCONNECT: /* JOIN disconnect */
3435 case MESSAGE_RELEASE: /* JOIN releases */
3436 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received %s with cause %d location %d\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, (message_type==MESSAGE_DISCONNECT)?"disconnect":"release", param->disconnectinfo.cause, param->disconnectinfo.location);
3437 join_disconnect_release(message_type, param);
3440 /* JOIN sends SETUP message */
3442 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint received setup from terminal='%s',id='%s' to id='%s' (dialing itype=%d)\n", ea_endpoint->ep_serial, param->setup.callerinfo.extension, param->setup.callerinfo.id, param->setup.dialinginfo.id, param->setup.dialinginfo.itype);
3443 join_setup(portlist, message_type, param);
3446 /* JOIN sends special mISDNSIGNAL message */
3447 case MESSAGE_mISDNSIGNAL: /* isdn message to port */
3448 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received mISDNsignal message.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3449 join_mISDNsignal(portlist, message_type, param);
3453 kann nach dem test gelöscht werden, da eine direkte funktion im join und im mISDN zum austausch der message existiert
3454 /* JOIN requests bchannel */
3455 case MESSAGE_BCHANNEL: /* indicates the need of own bchannel access */
3456 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received bchannel assignment %d from join.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->bchannel.type);
3457 /* only one port is expected to be connected to bchannel */
3464 set_tone(portlist, NULL);
3465 message = message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3466 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3470 /* JOIN has pattern available */
3471 case MESSAGE_PATTERN: /* indicating pattern available */
3472 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received pattern availability.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3473 if (!e_join_pattern)
3475 PDEBUG(DEBUG_EPOINT, "-> pattern becomes available\n");
3480 set_tone(portlist, NULL);
3481 portlist = portlist->next;
3483 /* connect our audio tx and rx (blueboxing should be possibe before connect :)*/
3484 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3485 message->param.audiopath = 1;
3486 message_put(message);
3490 /* JOIN has no pattern available */
3491 case MESSAGE_NOPATTERN: /* indicating no pattern available */
3492 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received pattern NOT available.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3495 PDEBUG(DEBUG_EPOINT, "-> pattern becomes unavailable\n");
3497 /* disconnect our audio tx and rx */
3498 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3499 message->param.audiopath = 0;
3500 message_put(message);
3505 /* JOIN (dunno at the moment) */
3506 case MESSAGE_REMOTE_AUDIO:
3507 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received audio remote request.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3508 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3509 message->param.audiopath = param->channel;
3510 message_put(message);
3514 /* JOIN sends a notify message */
3515 case MESSAGE_NOTIFY:
3516 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);
3517 join_notify(portlist, message_type, param);
3520 /* JOIN wants keypad / dtml */
3521 case MESSAGE_ENABLEKEYPAD:
3522 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received keypad enable request.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3525 trace_header("ENABLE KEYPAD", DIRECTION_NONE);
3530 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);
3535 /* pick_join will connect the first incoming call found. the endpoint
3536 * will receivce a MESSAGE_CONNECT.
3538 int match_list(char *list, char *item)
3540 char *end, *next = NULL;
3542 /* no list make matching */
3548 /* eliminate white spaces */
3549 while (*list <= ' ')
3556 /* if end of list is reached, we return */
3557 if (list[0] == '\0')
3559 /* if we have more than one entry (left) */
3560 if ((end = strchr(list, ',')))
3563 next = end = strchr(list, '\0');
3564 while (*(end-1) <= ' ')
3566 /* if string part matches item */
3567 if (!strncmp(list, item, end-list))
3573 void EndpointAppPBX::pick_join(char *extensions)
3575 struct lcr_msg *message;
3576 struct port_list *portlist;
3578 class EndpointAppPBX *eapp, *found;
3580 class JoinPBX *joinpbx;
3581 struct join_relation *relation;
3584 /* find an endpoint that is ringing internally or vbox with higher priority */
3587 eapp = apppbx_first;
3590 if (eapp!=this && ea_endpoint->ep_portlist)
3592 portlist = eapp->ea_endpoint->ep_portlist;
3595 if ((port = find_port_id(portlist->port_id)))
3597 if (port->p_type == PORT_TYPE_VBOX_OUT)
3599 if (match_list(extensions, eapp->e_ext.number))
3606 if ((port->p_type==PORT_TYPE_DSS1_NT_OUT || port->p_type==PORT_TYPE_DSS1_TE_OUT)
3607 && port->p_state==PORT_STATE_OUT_ALERTING)
3608 if (match_list(extensions, eapp->e_ext.number))
3613 portlist = portlist->next;
3621 /* if no endpoint found */
3624 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) nobody is ringing internally (or we don't have her in the access list), so we disconnect.\n", ea_endpoint->ep_serial);
3626 set_tone(ea_endpoint->ep_portlist, "cause_10");
3627 message_disconnect_port(ea_endpoint->ep_portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
3628 new_state(EPOINT_STATE_OUT_DISCONNECT);
3633 if (ea_endpoint->ep_join_id)
3635 PERROR("EPOINT(%d) we already have a join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3638 if (!eapp->ea_endpoint->ep_join_id)
3640 PERROR("EPOINT(%d) ringing endpoint has no join.\n", ea_endpoint->ep_serial);
3643 join = find_join_id(eapp->ea_endpoint->ep_join_id);
3646 PERROR("EPOINT(%d) ringing endpoint's join not found.\n", ea_endpoint->ep_serial);
3649 if (join->j_type != JOIN_TYPE_PBX)
3651 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ringing endpoint's join is not a PBX join, so we must reject.\n", ea_endpoint->ep_serial);
3654 joinpbx = (class JoinPBX *)join;
3655 relation = joinpbx->j_relation;
3658 PERROR("EPOINT(%d) ringing endpoint's join has no relation. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3661 while (relation->epoint_id != eapp->ea_endpoint->ep_serial)
3663 relation = relation->next;
3666 PERROR("EPOINT(%d) ringing endpoint's join has no relation to that join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3671 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found ringing endpoint: %d.\n", ea_endpoint->ep_serial, eapp->ea_endpoint->ep_serial);
3673 if (options.deb & DEBUG_EPOINT)
3675 class Join *debug_c = join_first;
3676 class Endpoint *debug_e = epoint_first;
3677 class Port *debug_p = port_first;
3679 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(before)");
3681 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3684 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3685 debug_c = debug_c->next;
3687 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3690 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3691 debug_e = debug_e->next;
3693 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3696 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld (active)\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3697 debug_p = debug_p->next;
3702 ea_endpoint->ep_join_id = eapp->ea_endpoint->ep_join_id; /* we get the join */
3703 relation->epoint_id = ea_endpoint->ep_serial; /* the join gets us */
3704 eapp->ea_endpoint->ep_join_id = 0; /* the ringing endpoint will get disconnected */
3706 /* connnecting our endpoint */
3707 new_state(EPOINT_STATE_CONNECT);
3708 if (e_ext.number[0])
3710 set_tone(ea_endpoint->ep_portlist, NULL);
3712 /* now we send a release to the ringing endpoint */
3713 message = message_create(ea_endpoint->ep_join_id, eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3714 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
3715 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3716 message_put(message);
3718 /* we send a connect to the join with our caller id */
3719 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CONNECT);
3720 SCPY(message->param.connectinfo.id, e_callerinfo.id);
3721 message->param.connectinfo.present = e_callerinfo.present;
3722 message->param.connectinfo.screen = e_callerinfo.screen;
3723 message->param.connectinfo.itype = e_callerinfo.itype;
3724 message->param.connectinfo.ntype = e_callerinfo.ntype;
3725 message_put(message);
3727 /* we send a connect to our port with the remote callerid */
3728 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3729 SCPY(message->param.connectinfo.id, eapp->e_callerinfo.id);
3730 message->param.connectinfo.present = eapp->e_callerinfo.present;
3731 message->param.connectinfo.screen = eapp->e_callerinfo.screen;
3732 message->param.connectinfo.itype = eapp->e_callerinfo.itype;
3733 message->param.connectinfo.ntype = eapp->e_callerinfo.ntype;
3734 /* handle restricted caller ids */
3735 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);
3736 /* display callerid if desired for extension */
3737 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));
3738 message_put(message);
3740 /* we send a connect to the audio path (not for vbox) */
3741 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3742 message->param.audiopath = 1;
3743 message_put(message);
3745 /* beeing paranoid, we make call update */
3746 joinpbx->j_updatebridge = 1;
3748 if (options.deb & DEBUG_EPOINT)
3750 class Join *debug_c = join_first;
3751 class Endpoint *debug_e = epoint_first;
3752 class Port *debug_p = port_first;
3754 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(after)");
3756 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3759 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3760 debug_c = debug_c->next;
3762 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3765 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3766 debug_e = debug_e->next;
3768 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3771 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3772 debug_p = debug_p->next;
3778 /* join calls (look for a join that is on hold (same isdn interface/terminal))
3780 void EndpointAppPBX::join_join(void)
3782 struct lcr_msg *message;
3783 struct join_relation *our_relation, *other_relation;
3784 struct join_relation **our_relation_pointer, **other_relation_pointer;
3785 class Join *our_join, *other_join;
3786 class JoinPBX *our_joinpbx, *other_joinpbx;
3787 class EndpointAppPBX *other_eapp; class Endpoint *temp_epoint;
3788 class Port *our_port, *other_port;
3789 class Pdss1 *our_pdss1, *other_pdss1;
3791 /* are we a candidate to join a join */
3792 our_join = find_join_id(ea_endpoint->ep_join_id);
3795 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3798 if (our_join->j_type != JOIN_TYPE_PBX)
3800 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: join is not a pbx join.\n", ea_endpoint->ep_serial);
3803 our_joinpbx = (class JoinPBX *)our_join;
3804 if (!ea_endpoint->ep_portlist)
3806 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
3809 if (!e_ext.number[0])
3811 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
3814 our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
3817 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
3820 if ((our_port->p_type&PORT_CLASS_mISDN_MASK) != PORT_CLASS_mISDN_DSS1)
3822 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not isdn.\n", ea_endpoint->ep_serial);
3825 our_pdss1 = (class Pdss1 *)our_port;
3827 /* find an endpoint that is on hold and has the same mISDNport that we are on */
3828 other_eapp = apppbx_first;
3831 if (other_eapp == this)
3833 other_eapp = other_eapp->next;
3836 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint candiate: (ep%d) terminal='%s' port=%s join=%d.\n", ea_endpoint->ep_serial, other_eapp->ea_endpoint->ep_serial, other_eapp->e_ext.number, (other_eapp->ea_endpoint->ep_portlist)?"YES":"NO", other_eapp->ea_endpoint->ep_join_id);
3837 if (other_eapp->e_ext.number[0] /* has terminal */
3838 && other_eapp->ea_endpoint->ep_portlist /* has port */
3839 && other_eapp->ea_endpoint->ep_join_id) /* has join */
3841 other_port = find_port_id(other_eapp->ea_endpoint->ep_portlist->port_id);
3842 if (other_port) /* port still exists */
3844 if (other_port->p_type==PORT_TYPE_DSS1_NT_OUT
3845 || other_port->p_type==PORT_TYPE_DSS1_NT_IN) /* port is isdn nt-mode */
3847 other_pdss1 = (class Pdss1 *)other_port;
3848 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of type isdn! comparing our portnum=%d with other's portnum=%d hold=%s ces=%d\n", ea_endpoint->ep_serial, our_pdss1->p_m_mISDNport->portnum, other_pdss1->p_m_mISDNport->portnum, (other_pdss1->p_m_hold)?"YES":"NO", other_pdss1->p_m_d_ces);
3849 if (other_pdss1->p_m_hold /* port is on hold */
3850 && other_pdss1->p_m_mISDNport == our_pdss1->p_m_mISDNport /* same isdn interface */
3851 && other_pdss1->p_m_d_ces == our_pdss1->p_m_d_ces) /* same tei+sapi */
3855 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of other type!\n", ea_endpoint->ep_serial);
3859 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port doesn't exist enymore.\n", ea_endpoint->ep_serial);
3862 other_eapp = other_eapp->next;
3866 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn interface with port on hold.\n", ea_endpoint->ep_serial);
3869 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port on hold found.\n", ea_endpoint->ep_serial);
3871 /* if we have the same join */
3872 if (other_eapp->ea_endpoint->ep_join_id == ea_endpoint->ep_join_id)
3874 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we an the other have the same join.\n", ea_endpoint->ep_serial);
3877 other_join = find_join_id(other_eapp->ea_endpoint->ep_join_id);
3880 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3883 if (other_join->j_type != JOIN_TYPE_PBX)
3885 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join is not a pbx join.\n", ea_endpoint->ep_serial);
3888 other_joinpbx = (class JoinPBX *)other_join;
3889 if (our_joinpbx->j_partyline && other_joinpbx->j_partyline)
3891 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both joins are partylines.\n", ea_endpoint->ep_serial);
3895 /* remove relation to endpoint for join on hold */
3896 other_relation = other_joinpbx->j_relation;
3897 other_relation_pointer = &other_joinpbx->j_relation;
3898 while(other_relation)
3900 if (other_relation->epoint_id == other_eapp->ea_endpoint->ep_serial)
3902 /* detach other endpoint on hold */
3903 *other_relation_pointer = other_relation->next;
3904 FREE(other_relation, sizeof(struct join_relation));
3906 other_relation = *other_relation_pointer;
3907 other_eapp->ea_endpoint->ep_join_id = 0;
3911 /* change join/hold pointer of endpoint to the new join */
3912 temp_epoint = find_epoint_id(other_relation->epoint_id);
3915 if (temp_epoint->ep_join_id == other_join->j_serial)
3916 temp_epoint->ep_join_id = our_join->j_serial;
3919 other_relation_pointer = &other_relation->next;
3920 other_relation = other_relation->next;
3922 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint on hold removed, other enpoints on join relinked (to our join).\n", ea_endpoint->ep_serial);
3924 /* join call relations */
3925 our_relation = our_joinpbx->j_relation;
3926 our_relation_pointer = &our_joinpbx->j_relation;
3929 our_relation_pointer = &our_relation->next;
3930 our_relation = our_relation->next;
3932 *our_relation_pointer = other_joinpbx->j_relation;
3933 other_joinpbx->j_relation = NULL;
3934 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) relations joined.\n", ea_endpoint->ep_serial);
3936 /* release endpoint on hold */
3937 message = message_create(other_joinpbx->j_serial, other_eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3938 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */
3939 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3940 message_put(message);
3942 /* if we are not a partyline, we get partyline state from other join */
3943 our_joinpbx->j_partyline += other_joinpbx->j_partyline;
3945 /* remove empty join */
3947 PDEBUG(DEBUG_EPOINT, "EPOINT(%d)d-join completely removed!\n");
3949 /* mixer must update */
3950 our_joinpbx->j_updatebridge = 1; /* update mixer flag */
3952 /* we send a retrieve to that endpoint */
3953 // mixer will update the hold-state of the join and send it to the endpoints is changes
3957 /* check if we have an external call
3958 * this is used to check for encryption ability
3960 int EndpointAppPBX::check_external(char **errstr, class Port **port)
3962 struct join_relation *relation;
3964 class JoinPBX *joinpbx;
3965 class Endpoint *epoint;
3967 /* some paranoia check */
3968 if (!ea_endpoint->ep_portlist)
3970 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we have no port.\n", ea_endpoint->ep_serial);
3971 *errstr = "No Call";
3974 if (!e_ext.number[0])
3976 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we are not internal extension.\n", ea_endpoint->ep_serial);
3977 *errstr = "No Call";
3981 /* check if we have a join with 2 parties */
3982 join = find_join_id(ea_endpoint->ep_join_id);
3985 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have currently no join.\n", ea_endpoint->ep_serial);
3986 *errstr = "No Call";
3989 if (join->j_type != JOIN_TYPE_PBX)
3991 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join is not a pbx join.\n", ea_endpoint->ep_serial);
3992 *errstr = "No PBX Call";
3995 joinpbx = (class JoinPBX *)join;
3996 relation = joinpbx->j_relation;
3999 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no relation.\n", ea_endpoint->ep_serial);
4000 *errstr = "No Call";
4003 if (!relation->next)
4005 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd relation.\n", ea_endpoint->ep_serial);
4006 *errstr = "No Call";
4009 if (relation->next->next)
4011 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has more than two relations.\n", ea_endpoint->ep_serial);
4012 *errstr = "Err: Conference";
4015 if (relation->epoint_id == ea_endpoint->ep_serial)
4017 relation = relation->next;
4018 if (relation->epoint_id == ea_endpoint->ep_serial)
4020 PERROR("EPOINT(%d) SOFTWARE ERROR: both join relations are related to our endpoint.\n", ea_endpoint->ep_serial);
4021 *errstr = "Software Error";
4026 /* check remote port for external call */
4027 epoint = find_epoint_id(relation->epoint_id);
4030 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd endpoint.\n", ea_endpoint->ep_serial);
4031 *errstr = "No Call";
4034 if (!epoint->ep_portlist)
4036 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not port.\n", ea_endpoint->ep_serial);
4037 *errstr = "No Call";
4040 *port = find_port_id(epoint->ep_portlist->port_id);
4043 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has an none existing port.\n", ea_endpoint->ep_serial);
4044 *errstr = "No Call";
4047 if (((*port)->p_type&PORT_CLASS_mISDN_MASK)!=PORT_CLASS_mISDN_DSS1) /* port is not external isdn */
4049 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not an external port.\n", ea_endpoint->ep_serial);
4050 *errstr = "No Ext Call";
4053 if ((*port)->p_state != PORT_STATE_CONNECT)
4055 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint's port is not in connected state.\n", ea_endpoint->ep_serial);
4056 *errstr = "No Ext Connect";
4062 void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsigned int port_id, int dir)
4064 char *logtext = "unknown";
4067 switch(message_type)
4070 trace_header("SETUP", dir);
4071 if (dir == DIRECTION_OUT)
4072 add_trace("to", NULL, "CH(%lu)", port_id);
4073 if (dir == DIRECTION_IN)
4074 add_trace("from", NULL, "CH(%lu)", port_id);
4075 if (param->setup.callerinfo.extension[0])
4076 add_trace("extension", NULL, "%s", param->setup.callerinfo.extension);
4077 add_trace("caller id", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype, options.national, options.international));
4078 switch(param->setup.callerinfo.present)
4080 case INFO_PRESENT_RESTRICTED:
4081 add_trace("caller id", "present", "restricted");
4083 case INFO_PRESENT_ALLOWED:
4084 add_trace("caller id", "present", "allowed");
4087 add_trace("caller id", "present", "not available");
4089 if (param->setup.redirinfo.id[0])
4091 add_trace("redir'ing", "number", "%s", numberrize_callerinfo(param->setup.redirinfo.id, param->setup.redirinfo.ntype, options.national, options.international));
4092 switch(param->setup.redirinfo.present)
4094 case INFO_PRESENT_RESTRICTED:
4095 add_trace("redir'ing", "present", "restricted");
4097 case INFO_PRESENT_ALLOWED:
4098 add_trace("redir'ing", "present", "allowed");
4101 add_trace("redir'ing", "present", "not available");
4104 if (param->setup.dialinginfo.id[0])
4105 add_trace("dialing", NULL, "%s", param->setup.dialinginfo.id);
4109 case MESSAGE_OVERLAP:
4110 trace_header("SETUP ACKNOWLEDGE", dir);
4111 if (dir == DIRECTION_OUT)
4112 add_trace("to", NULL, "CH(%lu)", port_id);
4113 if (dir == DIRECTION_IN)
4114 add_trace("from", NULL, "CH(%lu)", port_id);
4118 case MESSAGE_PROCEEDING:
4119 trace_header("PROCEEDING", dir);
4120 if (dir == DIRECTION_OUT)
4121 add_trace("to", NULL, "CH(%lu)", port_id);
4122 if (dir == DIRECTION_IN)
4123 add_trace("from", NULL, "CH(%lu)", port_id);
4127 case MESSAGE_ALERTING:
4128 trace_header("ALERTING", dir);
4129 if (dir == DIRECTION_OUT)
4130 add_trace("to", NULL, "CH(%lu)", port_id);
4131 if (dir == DIRECTION_IN)
4132 add_trace("from", NULL, "CH(%lu)", port_id);
4136 case MESSAGE_CONNECT:
4137 trace_header("CONNECT", dir);
4138 if (dir == DIRECTION_OUT)
4139 add_trace("to", NULL, "CH(%lu)", port_id);
4140 if (dir == DIRECTION_IN)
4141 add_trace("from", NULL, "CH(%lu)", port_id);
4142 if (param->connectinfo.extension[0])
4143 add_trace("extension", NULL, "%s", param->connectinfo.extension);
4144 add_trace("connect id", "number", "%s", numberrize_callerinfo(param->connectinfo.id, param->connectinfo.ntype, options.national, options.international));
4145 switch(param->connectinfo.present)
4147 case INFO_PRESENT_RESTRICTED:
4148 add_trace("connect id", "present", "restricted");
4150 case INFO_PRESENT_ALLOWED:
4151 add_trace("connect id", "present", "allowed");
4154 add_trace("connect id", "present", "not available");
4159 case MESSAGE_DISCONNECT:
4160 case MESSAGE_RELEASE:
4161 if (message_type == MESSAGE_DISCONNECT)
4162 trace_header("DISCONNECT", dir);
4164 trace_header("RELEASE", dir);
4165 if (dir == DIRECTION_OUT)
4166 add_trace("to", NULL, "CH(%lu)", port_id);
4167 if (dir == DIRECTION_IN)
4168 add_trace("from", NULL, "CH(%lu)", port_id);
4169 add_trace("cause", "value", "%d", param->disconnectinfo.cause);
4170 switch(param->disconnectinfo.location)
4173 add_trace("cause", "location", "0-User");
4175 case LOCATION_PRIVATE_LOCAL:
4176 add_trace("cause", "location", "1-Local-PBX");
4178 case LOCATION_PUBLIC_LOCAL:
4179 add_trace("cause", "location", "2-Local-Exchange");
4181 case LOCATION_TRANSIT:
4182 add_trace("cause", "location", "3-Transit");
4184 case LOCATION_PUBLIC_REMOTE:
4185 add_trace("cause", "location", "4-Remote-Exchange");
4187 case LOCATION_PRIVATE_REMOTE:
4188 add_trace("cause", "location", "5-Remote-PBX");
4190 case LOCATION_INTERNATIONAL:
4191 add_trace("cause", "location", "7-International-Exchange");
4193 case LOCATION_BEYOND:
4194 add_trace("cause", "location", "10-Beyond-Interworking");
4197 add_trace("cause", "location", "%d", param->disconnectinfo.location);
4202 case MESSAGE_NOTIFY:
4203 switch(param->notifyinfo.notify)
4209 logtext = "USER_SUSPENDED";
4212 logtext = "BEARER_SERVICE_CHANGED";
4215 logtext = "USER_RESUMED";
4218 logtext = "CONFERENCE_ESTABLISHED";
4221 logtext = "CONFERENCE_DISCONNECTED";
4224 logtext = "OTHER_PARTY_ADDED";
4227 logtext = "ISOLATED";
4230 logtext = "REATTACHED";
4233 logtext = "OTHER_PARTY_ISOLATED";
4236 logtext = "OTHER_PARTY_REATTACHED";
4239 logtext = "OTHER_PARTY_SPLIT";
4242 logtext = "OTHER_PARTY_DISCONNECTED";
4245 logtext = "CONFERENCE_FLOATING";
4248 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
4251 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
4254 logtext = "CALL_IS_A_WAITING_CALL";
4257 logtext = "DIVERSION_ACTIVATED";
4260 logtext = "RESERVED_CT_1";
4263 logtext = "RESERVED_CT_2";
4266 logtext = "REVERSE_CHARGING";
4269 logtext = "REMOTE_HOLD";
4272 logtext = "REMOTE_RETRIEVAL";
4275 logtext = "CALL_IS_DIVERTING";
4278 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
4282 trace_header("NOTIFY", dir);
4283 if (dir == DIRECTION_OUT)
4284 add_trace("to", NULL, "CH(%lu)", port_id);
4285 if (dir == DIRECTION_IN)
4286 add_trace("from", NULL, "CH(%lu)", port_id);
4287 if (param->notifyinfo.notify)
4288 add_trace("indicator", NULL, "%s", logtext);
4289 if (param->notifyinfo.id[0])
4291 add_trace("redir'on", "number", "%s", numberrize_callerinfo(param->notifyinfo.id, param->notifyinfo.ntype, options.national, options.international));
4292 switch(param->notifyinfo.present)
4294 case INFO_PRESENT_RESTRICTED:
4295 add_trace("redir'on", "present", "restricted");
4297 case INFO_PRESENT_ALLOWED:
4298 add_trace("redir'on", "present", "allowed");
4301 add_trace("redir'on", "present", "not available");
4304 if (param->notifyinfo.display[0])
4305 add_trace("display", NULL, "%s", param->notifyinfo.display);
4309 case MESSAGE_INFORMATION:
4310 trace_header("INFORMATION", dir);
4311 if (dir == DIRECTION_OUT)
4312 add_trace("to", NULL, "CH(%lu)", port_id);
4313 if (dir == DIRECTION_IN)
4314 add_trace("from", NULL, "CH(%lu)", port_id);
4315 add_trace("dialing", NULL, "%s", param->information.id);
4319 case MESSAGE_FACILITY:
4320 trace_header("FACILITY", dir);
4321 if (dir == DIRECTION_OUT)
4322 add_trace("to", NULL, "CH(%lu)", port_id);
4323 if (dir == DIRECTION_IN)
4324 add_trace("from", NULL, "CH(%lu)", port_id);
4329 trace_header("TONE", dir);
4330 if (dir == DIRECTION_OUT)
4331 add_trace("to", NULL, "CH(%lu)", port_id);
4332 if (dir == DIRECTION_IN)
4333 add_trace("from", NULL, "CH(%lu)", port_id);
4334 if (param->tone.name[0])
4336 add_trace("directory", NULL, "%s", param->tone.dir[0]?param->tone.dir:"default");
4337 add_trace("name", NULL, "%s", param->tone.name);
4339 add_trace("off", NULL, NULL);
4343 case MESSAGE_SUSPEND:
4344 case MESSAGE_RESUME:
4345 if (message_type == MESSAGE_SUSPEND)
4346 trace_header("SUSPEND", dir);
4348 trace_header("RESUME", dir);
4349 if (dir == DIRECTION_OUT)
4350 add_trace("to", NULL, "CH(%lu)", port_id);
4351 if (dir == DIRECTION_IN)
4352 add_trace("from", NULL, "CH(%lu)", port_id);
4353 if (param->parkinfo.len)
4354 add_trace("length", NULL, "%d", param->parkinfo.len);
4359 case MESSAGE_BCHANNEL:
4360 trace_header("BCHANNEL", dir);
4361 switch(param->bchannel.type)
4363 case BCHANNEL_REQUEST:
4364 add_trace("type", NULL, "request");
4366 case BCHANNEL_ASSIGN:
4367 add_trace("type", NULL, "assign");
4369 case BCHANNEL_ASSIGN_ACK:
4370 add_trace("type", NULL, "assign_ack");
4372 case BCHANNEL_REMOVE:
4373 add_trace("type", NULL, "remove");
4375 case BCHANNEL_REMOVE_ACK:
4376 add_trace("type", NULL, "remove_ack");
4379 if (param->bchannel.addr)
4380 add_trace("address", NULL, "%x", param->bchannel.addr);
4386 PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message_type);
4390 void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cause, int location, char *display)
4392 struct lcr_msg *message;
4396 if (!portlist->port_id)
4399 if (!e_connectedmode)
4401 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT);
4402 message->param.disconnectinfo.cause = cause;
4403 message->param.disconnectinfo.location = location;
4405 SCPY(message->param.disconnectinfo.display, display);
4407 SCPY(message->param.disconnectinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4410 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
4412 SCPY(message->param.notifyinfo.display, display);
4414 SCPY(message->param.notifyinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4416 message_put(message);
4417 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);