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)
1711 set_tone(portlist, "dialing");
1712 else if (!e_extdialing[0])
1713 set_tone(portlist, "dialing");
1715 /* concat dialing string */
1716 SCAT(e_dialinginfo.id, param->information.id);
1720 /* port MESSAGE_DTMF */
1721 void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
1723 /* only if dtmf detection is enabled */
1726 trace_header("DTMF (disabled)", DIRECTION_IN);
1730 trace_header("DTMF", DIRECTION_IN);
1731 add_trace("digit", NULL, "%c", param->dtmf);
1735 NOTE: vbox is now handled due to overlap state
1736 /* if vbox_play is done, the dtmf digits are just used as they come */
1738 if (e_action->index == ACTION_VBOX_PLAY)
1740 /* concat dialing string */
1741 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id))
1743 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1744 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1747 /* continue to process *X# sequences */
1751 /* check for *X# sequence */
1752 if (e_state == EPOINT_STATE_CONNECT)
1754 if (e_dtmf_time+3 < now)
1756 /* the last digit was too far in the past to be a sequence */
1757 if (param->dtmf == '*')
1758 /* only start is allowed in the sequence */
1764 /* we have a sequence of digits, see what we got */
1765 if (param->dtmf == '*')
1767 else if (param->dtmf>='0' && param->dtmf<='9')
1769 /* we need to have a star before we receive the digit of the sequence */
1770 if (e_dtmf_last == '*')
1771 e_dtmf_last = param->dtmf;
1772 } else if (param->dtmf == '#')
1775 if (e_dtmf_last>='0' && e_dtmf_last<='9')
1777 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf sequence *%c# detected.\n", ea_endpoint->ep_serial, e_dtmf_last);
1778 if (e_dtmf_last == '0')
1783 /* processing keypad function */
1785 keypad_function(e_dtmf_last);
1791 /* set last time of dtmf */
1796 /* check for ## hookflash during dialing */
1798 if (e_action->index==ACTION_PASSWORD
1799 || e_action->index==ACTION_PASSWORD_WRITE)
1801 if (param->dtmf=='#') /* current digit is '#' */
1803 if (e_state==EPOINT_STATE_IN_DISCONNECT
1804 || (e_state!=EPOINT_STATE_CONNECT && e_dtmf_time+3>=now && e_dtmf_last=='#')) /* when disconnected, just #. when dialing, ##. */
1821 /* dialing using dtmf digit */
1822 if (e_state==EPOINT_STATE_IN_OVERLAP)// && e_state==e_connectedmode)
1824 if (e_dialinginfo.id[0]=='\0' && !e_action)
1826 set_tone(portlist, "dialing");
1828 /* concat dialing string */
1829 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id))
1831 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1832 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1838 /* port MESSAGE_CRYPT */
1839 void EndpointAppPBX::port_crypt(struct port_list *portlist, int message_type, union parameter *param)
1841 /* send crypt response to cryptman */
1842 if (param->crypt.type == CR_MESSAGE_IND)
1843 cryptman_msg2man(param->crypt.data, param->crypt.len);
1845 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
1848 /* port MESSAGE_OVERLAP */
1849 void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, union parameter *param)
1851 struct lcr_msg *message;
1853 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1855 /* signal to call tool */
1856 admin_call_response(e_adminid, ADMIN_CALL_SETUP_ACK, "", 0, 0, 0);
1858 if (e_dialing_queue[0] && portlist)
1860 /* send what we have not dialed yet, because we had no setup complete */
1861 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing pending digits: '%s'\n", ea_endpoint->ep_serial, e_dialing_queue);
1862 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
1863 SCPY(message->param.information.id, e_dialing_queue);
1864 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
1865 message_put(message);
1866 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
1867 e_dialing_queue[0] = '\0';
1869 /* check if pattern is available */
1870 if (!ea_endpoint->ep_portlist->next && portlist->early_b) /* one port_list relation and tones available */
1872 /* indicate patterns */
1873 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1874 message_put(message);
1876 /* connect audio, if not already */
1877 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1878 message->param.audiopath = 1;
1879 message_put(message);
1882 /* indicate no patterns */
1883 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1884 message_put(message);
1886 /* disconnect audio, if not already */
1887 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1888 message->param.audiopath = 0;
1889 message_put(message);
1891 new_state(EPOINT_STATE_OUT_OVERLAP);
1892 /* if we are in a join */
1893 if (ea_endpoint->ep_join_id)
1895 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1896 memcpy(&message->param, param, sizeof(union parameter));
1897 message_put(message);
1901 /* port MESSAGE_PROCEEDING */
1902 void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_type, union parameter *param)
1904 struct lcr_msg *message;
1906 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1908 /* signal to call tool */
1909 admin_call_response(e_adminid, ADMIN_CALL_PROCEEDING, "", 0, 0, 0);
1911 e_state = EPOINT_STATE_OUT_PROCEEDING;
1912 /* check if pattern is availatle */
1913 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
1915 /* indicate patterns */
1916 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1917 message_put(message);
1919 /* connect audio, if not already */
1920 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1921 message->param.audiopath = 1;
1922 message_put(message);
1925 /* indicate no patterns */
1926 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1927 message_put(message);
1929 /* disconnect audio, if not already */
1930 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1931 message->param.audiopath = 0;
1932 message_put(message);
1934 /* if we are in a call */
1935 if (ea_endpoint->ep_join_id)
1937 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1938 memcpy(&message->param, param, sizeof(union parameter));
1939 message_put(message);
1943 /* port MESSAGE_ALERTING */
1944 void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type, union parameter *param)
1946 struct lcr_msg *message;
1948 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1950 /* signal to call tool */
1951 admin_call_response(e_adminid, ADMIN_CALL_ALERTING, "", 0, 0, 0);
1954 // set_tone(portlist, "hold");
1956 new_state(EPOINT_STATE_OUT_ALERTING);
1957 /* check if pattern is available */
1958 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
1960 /* indicate patterns */
1961 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1962 message_put(message);
1964 /* connect audio, if not already */
1965 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1966 message->param.audiopath = 1;
1967 message_put(message);
1970 /* indicate no patterns */
1971 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1972 message_put(message);
1974 /* disconnect audio, if not already */
1975 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1976 message->param.audiopath = 0;
1977 message_put(message);
1979 /* if we are in a call */
1980 if (ea_endpoint->ep_join_id)
1982 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1983 memcpy(&message->param, param, sizeof(union parameter));
1984 message_put(message);
1988 /* port MESSAGE_CONNECT */
1989 void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, union parameter *param)
1991 struct lcr_msg *message;
1993 unsigned int port_id = portlist->port_id;
1994 struct port_list *tportlist;
1996 struct interface *interface;
1998 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2000 /* signal to call tool */
2001 admin_call_response(e_adminid, ADMIN_CALL_CONNECT, numberrize_callerinfo(param->connectinfo.id,param->connectinfo.ntype, options.national, options.international), 0, 0, 0);
2003 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_connectinfo));
2004 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (start)\n", ea_endpoint->ep_serial);
2005 while(ea_endpoint->ep_portlist->next) /* as long as we have at least two ports */
2007 tportlist = ea_endpoint->ep_portlist;
2008 if (tportlist->port_id == port_id) /* if the first portlist is the calling one, the second must be a different one */
2009 tportlist = tportlist->next;
2010 if (tportlist->port_id == port_id)
2011 FATAL("EPOINT(%d) this should not happen since the portlist list must not have two links to the same port - exitting.\n");
2012 message = message_create(ea_endpoint->ep_serial, tportlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2013 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
2014 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2015 message_put(message);
2016 logmessage(message->type, &message->param, tportlist->port_id, DIRECTION_OUT);
2017 ea_endpoint->free_portlist(tportlist);
2019 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (end)\n", ea_endpoint->ep_serial);
2023 /* screen incoming connected id */
2024 interface = interface_first;
2027 if (!strcmp(e_connectinfo.interface, interface->name))
2031 interface = interface->next;
2034 do_screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface);
2036 /* screen connected name */
2038 SCPY(e_connectinfo.name, e_ext.name);
2040 /* add internal id to colp */
2041 SCPY(e_connectinfo.extension, e_ext.number);
2043 /* we store the connected port number */
2044 SCPY(e_extension_interface, e_connectinfo.interface);
2046 /* for internal and am calls, we get the extension's id */
2047 if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE)
2049 SCPY(e_connectinfo.id, e_ext.callerid);
2050 SCPY(e_connectinfo.extension, e_ext.number);
2051 e_connectinfo.itype = INFO_ITYPE_ISDN_EXTENSION;
2052 e_connectinfo.ntype = e_ext.callerid_type;
2053 e_connectinfo.present = e_ext.callerid_present;
2055 if (portlist->port_type==PORT_TYPE_VBOX_OUT)
2057 e_connectinfo.itype = INFO_ITYPE_VBOX;
2058 e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2061 new_state(EPOINT_STATE_CONNECT);
2063 /* set volume of rx and tx */
2064 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
2066 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2067 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2068 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
2069 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
2070 message_put(message);
2073 e_cfnr_call = e_cfnr_release = 0;
2074 if (e_ext.number[0])
2075 e_dtmf = 1; /* allow dtmf */
2078 /* other calls with no caller id (or not available for the extension) and force colp */
2079 if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE)
2081 e_connectinfo.present = INFO_PRESENT_NOTAVAIL;
2082 if (portlist->port_type==PORT_TYPE_DSS1_TE_OUT || portlist->port_type==PORT_TYPE_DSS1_NT_OUT) /* external extension answered */
2084 port = find_port_id(portlist->port_id);
2087 SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.id, &e_connectinfo.ntype, options.national, options.international));
2088 e_connectinfo.present = INFO_PRESENT_ALLOWED;
2093 /* send connect to join */
2094 if (ea_endpoint->ep_join_id)
2096 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2097 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
2098 message_put(message);
2100 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2101 message->param.audiopath = 1;
2102 message_put(message);
2103 } else if (!e_adminid)
2106 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have a callback, so we create a call with cbcaller: \"%s\".\n", ea_endpoint->ep_serial, e_cbcaller);
2107 SCPY(e_ext.number, e_cbcaller);
2108 new_state(EPOINT_STATE_IN_OVERLAP);
2109 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) callback from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2111 /* get extension's info about terminal */
2112 if (!read_extension(&e_ext, e_ext.number))
2114 /* extension doesn't exist */
2115 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2116 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
2117 new_state(EPOINT_STATE_OUT_DISCONNECT);
2118 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
2122 /* put prefix in front of e_cbdialing */
2123 SPRINT(buffer, "%s%s", e_ext.prefix, e_cbdialing);
2124 SCPY(e_dialinginfo.id, buffer);
2125 e_dialinginfo.itype = INFO_ITYPE_ISDN;
2126 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
2128 /* use caller id (or if exist: id_next_call) for this call */
2129 e_callerinfo.screen = INFO_SCREEN_NETWORK;
2130 SCPY(e_callerinfo.extension, e_ext.number);
2131 if (e_ext.id_next_call_present >= 0)
2133 SCPY(e_callerinfo.id, e_ext.id_next_call);
2134 e_callerinfo.present = e_ext.id_next_call_present;
2135 e_callerinfo.ntype = e_ext.id_next_call_type;
2136 e_ext.id_next_call_present = -1;
2137 /* extension is written */
2138 write_extension(&e_ext, e_ext.number);
2141 SCPY(e_callerinfo.id, e_ext.callerid);
2142 e_callerinfo.present = e_ext.callerid_present;
2143 e_callerinfo.ntype = e_ext.callerid_type;
2146 e_connectedmode = 1; /* dtmf-hangup & disconnect prevention */
2149 /* check if caller id is NOT authenticated */
2150 if (!parse_callbackauth(e_ext.number, &e_callbackinfo))
2152 /* make call state to enter password */
2153 new_state(EPOINT_STATE_IN_OVERLAP);
2154 e_action = &action_password_write;
2155 e_match_timeout = 0;
2156 e_match_to_action = NULL;
2157 e_dialinginfo.id[0] = '\0';
2158 e_extdialing = strchr(e_dialinginfo.id, '\0');
2159 e_password_timeout = now+20;
2163 /* incoming call (callback) */
2164 e_ruleset = ruleset_main;
2166 e_rule = e_ruleset->rule_first;
2168 e_extdialing = e_dialinginfo.id;
2169 if (e_dialinginfo.id[0])
2171 set_tone(portlist, "dialing");
2175 set_tone(portlist, "dialpbx");
2178 } else /* testcall */
2180 set_tone(portlist, "hold");
2183 /* start recording if enabled, not when answering machine answers */
2184 if (param->connectinfo.itype!=INFO_ITYPE_VBOX && e_ext.number[0] && e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO))
2186 /* check if we are a terminal */
2187 if (e_ext.number[0] == '\0')
2188 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
2191 port = find_port_id(portlist->port_id);
2193 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
2198 /* port MESSAGE_DISCONNECT MESSAGE_RELEASE */
2199 void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
2201 struct lcr_msg *message;
2203 unsigned int port_id = portlist->port_id;
2207 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2209 /* signal to call tool */
2210 admin_call_response(e_adminid, (message_type==MESSAGE_DISCONNECT)?ADMIN_CALL_DISCONNECT:ADMIN_CALL_RELEASE, "", param->disconnectinfo.cause, param->disconnectinfo.location, 0);
2212 //#warning does this work? only disconnect when incoming port hat not already disconnected yet?
2213 if (e_state==EPOINT_STATE_IN_DISCONNECT && message_type!=MESSAGE_RELEASE)// || e_state==EPOINT_STATE_OUT_DISCONNECT || e_state==EPOINT_STATE_IDLE)
2215 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are already disconnected.\n", ea_endpoint->ep_serial);
2220 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);
2221 collect_cause(&e_multipoint_cause, &e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location);
2222 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new multipoint cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location);
2224 /* check if we have more than one portlist relation and we just ignore the disconnect */
2225 if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist->next)
2227 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the disconnect was from a multipoint call. we just release that relation.\n", ea_endpoint->ep_serial);
2228 portlist = ea_endpoint->ep_portlist;
2231 if (portlist->port_id == port_id)
2233 portlist = portlist->next;
2236 FATAL("EPOINT(%d) no portlist related to the calling port.\n", ea_endpoint->ep_serial);
2237 if (message_type != MESSAGE_RELEASE)
2239 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2240 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2241 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2242 message_put(message);
2243 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2245 ea_endpoint->free_portlist(portlist);
2246 return; /* one relation removed */
2248 if (e_state == EPOINT_STATE_CONNECT)
2250 /* use cause from port after connect */
2251 cause = param->disconnectinfo.cause;
2252 location = param->disconnectinfo.location;
2255 /* use multipoint cause if no connect yet */
2256 if (e_multipoint_cause)
2258 cause = e_multipoint_cause;
2259 location = e_multipoint_location;
2262 cause = CAUSE_NOUSER;
2263 location = LOCATION_PRIVATE_LOCAL;
2267 e_cfnr_call = e_cfnr_release = 0;
2269 /* process hangup */
2270 process_hangup(e_join_cause, e_join_location);
2271 e_multipoint_cause = 0;
2272 e_multipoint_location = 0;
2274 if (message_type == MESSAGE_DISCONNECT)
2276 /* tone to disconnected end */
2277 SPRINT(buffer, "cause_%02x", cause);
2278 if (ea_endpoint->ep_portlist)
2279 set_tone(ea_endpoint->ep_portlist, buffer);
2281 new_state(EPOINT_STATE_IN_DISCONNECT);
2284 if (ea_endpoint->ep_join_id)
2286 int haspatterns = 0;
2287 /* check if pattern is available */
2288 if (ea_endpoint->ep_portlist)
2289 if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->early_b)
2290 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
2291 && message_type != MESSAGE_RELEASE) // if we release, we are done
2295 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has patterns.\n", ea_endpoint->ep_serial);
2296 /* indicate patterns */
2297 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2298 message_put(message);
2299 /* connect audio, if not already */
2300 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2301 message->param.audiopath = 1;
2302 message_put(message);
2303 /* send disconnect */
2304 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2305 memcpy(&message->param, param, sizeof(union parameter));
2306 message_put(message);
2307 /* disable encryption if disconnected */
2308 //PERROR("REMOVE ME: state =%d, %d\n", e_crypt_state, e_crypt);
2310 cryptman_message(CI_DISCONNECT_IND, NULL, 0);
2314 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
2317 if (message_type == MESSAGE_RELEASE)
2318 ea_endpoint->free_portlist(portlist);
2319 release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, callcause, portcause */
2320 return; /* must exit here */
2323 /* port MESSAGE_TIMEOUT */
2324 void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type, union parameter *param)
2328 trace_header("TIMEOUT", DIRECTION_IN);
2329 message_type = MESSAGE_DISCONNECT;
2330 switch (param->state)
2332 case PORT_STATE_OUT_SETUP:
2333 case PORT_STATE_OUT_OVERLAP:
2334 add_trace("state", NULL, "outgoing setup/dialing");
2336 /* no user responding */
2337 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2338 return; /* must exit here */
2340 case PORT_STATE_IN_SETUP:
2341 case PORT_STATE_IN_OVERLAP:
2342 add_trace("state", NULL, "incoming setup/dialing");
2343 param->disconnectinfo.cause = CAUSE_INVALID; /* number incomplete */
2344 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2347 case PORT_STATE_OUT_PROCEEDING:
2348 add_trace("state", NULL, "outgoing proceeding");
2350 param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
2351 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2352 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2353 return; /* must exit here */
2355 case PORT_STATE_IN_PROCEEDING:
2356 add_trace("state", NULL, "incoming proceeding");
2357 param->disconnectinfo.cause = CAUSE_NOUSER;
2358 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL; /* no user responding */
2361 case PORT_STATE_OUT_ALERTING:
2362 add_trace("state", NULL, "outgoing alerting");
2364 param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
2365 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2366 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2367 return; /* must exit here */
2369 case PORT_STATE_CONNECT:
2370 add_trace("state", NULL, "connect");
2372 param->disconnectinfo.cause = CAUSE_NORMAL; /* normal */
2373 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2374 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2375 return; /* must exit here */
2377 case PORT_STATE_IN_ALERTING:
2378 add_trace("state", NULL, "incoming alerting");
2379 param->disconnectinfo.cause = CAUSE_NOANSWER;
2380 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2383 case PORT_STATE_IN_DISCONNECT:
2384 case PORT_STATE_OUT_DISCONNECT:
2385 add_trace("state", NULL, "disconnect");
2387 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
2388 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2389 return; /* must exit here */
2392 param->disconnectinfo.cause = 31; /* normal unspecified */
2393 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2396 /* release call, disconnect isdn */
2398 new_state(EPOINT_STATE_OUT_DISCONNECT);
2399 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2400 SCPY(e_tone, cause);
2403 set_tone(portlist, cause);
2404 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2405 portlist = portlist->next;
2407 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
2410 /* port MESSAGE_NOTIFY */
2411 void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, union parameter *param)
2413 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2415 struct lcr_msg *message;
2419 /* signal to call tool */
2420 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);
2421 if (param->notifyinfo.notify)
2423 e_rx_state = track_notify(e_rx_state, param->notifyinfo.notify);
2426 /* if we get notification from stack, local shows if we disabled/enabled audio stream */
2427 if (param->notifyinfo.local) switch(param->notifyinfo.notify)
2429 case INFO_NOTIFY_REMOTE_HOLD:
2430 case INFO_NOTIFY_USER_SUSPENDED:
2431 /* tell call about it */
2432 if (ea_endpoint->ep_join_id)
2434 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2435 message->param.audiopath = 0;
2436 message_put(message);
2440 case INFO_NOTIFY_REMOTE_RETRIEVAL:
2441 case INFO_NOTIFY_USER_RESUMED:
2442 /* set volume of rx and tx */
2443 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
2444 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
2447 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2448 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2449 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
2450 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
2451 message_put(message);
2453 /* set current tone */
2455 set_tone(portlist, e_tone);
2456 /* tell call about it */
2457 if (ea_endpoint->ep_join_id)
2459 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2460 message->param.audiopath = 1;
2461 message_put(message);
2466 /* get name of notify */
2467 switch(param->notifyinfo.notify)
2473 logtext = "USER_SUSPENDED";
2476 logtext = "BEARER_SERVICE_CHANGED";
2479 logtext = "USER_RESUMED";
2482 logtext = "CONFERENCE_ESTABLISHED";
2485 logtext = "CONFERENCE_DISCONNECTED";
2488 logtext = "OTHER_PARTY_ADDED";
2491 logtext = "ISOLATED";
2494 logtext = "REATTACHED";
2497 logtext = "OTHER_PARTY_ISOLATED";
2500 logtext = "OTHER_PARTY_REATTACHED";
2503 logtext = "OTHER_PARTY_SPLIT";
2506 logtext = "OTHER_PARTY_DISCONNECTED";
2509 logtext = "CONFERENCE_FLOATING";
2512 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
2515 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
2518 logtext = "CALL_IS_A_WAITING_CALL";
2521 logtext = "DIVERSION_ACTIVATED";
2524 logtext = "RESERVED_CT_1";
2527 logtext = "RESERVED_CT_2";
2530 logtext = "REVERSE_CHARGING";
2533 logtext = "REMOTE_HOLD";
2536 logtext = "REMOTE_RETRIEVAL";
2539 logtext = "CALL_IS_DIVERTING";
2542 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
2547 /* notify call if available */
2548 if (ea_endpoint->ep_join_id)
2550 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOTIFY);
2551 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
2552 message_put(message);
2557 /* port MESSAGE_FACILITY */
2558 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
2560 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2562 struct lcr_msg *message;
2564 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_FACILITY);
2565 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2566 message_put(message);
2569 /* port MESSAGE_SUSPEND */
2570 /* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
2571 void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
2573 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2575 /* epoint is now parked */
2576 ea_endpoint->ep_park = 1;
2577 memcpy(ea_endpoint->ep_park_callid, param->parkinfo.callid, sizeof(ea_endpoint->ep_park_callid));
2578 ea_endpoint->ep_park_len = (param->parkinfo.len>8)?8:param->parkinfo.len;
2580 /* remove port relation */
2581 ea_endpoint->free_portlist(portlist);
2584 /* port MESSAGE_RESUME */
2585 /* NOTE: before resume, the active-notification must be done in order to set call mixer */
2586 void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
2588 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2590 /* epoint is now resumed */
2591 ea_endpoint->ep_park = 0;
2596 /* port sends message to the endpoint
2598 void EndpointAppPBX::ea_message_port(unsigned int port_id, int message_type, union parameter *param)
2600 struct port_list *portlist;
2601 struct lcr_msg *message;
2603 portlist = ea_endpoint->ep_portlist;
2606 if (port_id == portlist->port_id)
2608 portlist = portlist->next;
2612 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);
2616 // PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
2617 switch(message_type)
2619 case MESSAGE_DATA: /* data from port */
2620 /* check if there is a call */
2621 if (!ea_endpoint->ep_join_id)
2623 /* continue if only one portlist */
2624 if (ea_endpoint->ep_portlist->next != NULL)
2626 /* forward message */
2627 message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2630 case MESSAGE_TONE_EOF: /* tone is end of file */
2631 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
2634 if (e_action->index == ACTION_VBOX_PLAY)
2638 if (e_action->index == ACTION_EFI)
2645 case MESSAGE_TONE_COUNTER: /* counter info received */
2646 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);
2648 if (e_action->index == ACTION_VBOX_PLAY)
2650 e_vbox_counter = param->counter.current;
2651 if (param->counter.max >= 0)
2652 e_vbox_counter_max = param->counter.max;
2656 /* PORT sends SETUP message */
2658 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);
2659 if (e_state!=EPOINT_STATE_IDLE)
2661 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
2664 port_setup(portlist, message_type, param);
2667 /* PORT sends INFORMATION message */
2668 case MESSAGE_INFORMATION: /* additional digits received */
2669 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call dialing more=%s (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, param->information.id, e_ext.number, e_callerinfo.id);
2670 port_information(portlist, message_type, param);
2673 /* PORT sends FACILITY message */
2674 case MESSAGE_FACILITY:
2675 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2676 port_facility(portlist, message_type, param);
2679 /* PORT sends DTMF message */
2680 case MESSAGE_DTMF: /* dtmf digits received */
2681 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf digit=%c (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, param->dtmf, e_ext.number, e_callerinfo.id);
2682 port_dtmf(portlist, message_type, param);
2685 /* PORT sends CRYPT message */
2686 case MESSAGE_CRYPT: /* crypt response received */
2687 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) crypt response=%d\n", ea_endpoint->ep_serial, param->crypt.type);
2688 port_crypt(portlist, message_type, param);
2691 /* PORT sends MORE message */
2692 case MESSAGE_OVERLAP:
2693 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) outgoing call is accepted [overlap dialing] (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2694 if (e_state != EPOINT_STATE_OUT_SETUP)
2696 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);
2699 port_overlap(portlist, message_type, param);
2702 /* PORT sends PROCEEDING message */
2703 case MESSAGE_PROCEEDING: /* port is proceeding */
2704 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);
2705 if (e_state!=EPOINT_STATE_OUT_SETUP
2706 && e_state!=EPOINT_STATE_OUT_OVERLAP)
2708 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);
2711 port_proceeding(portlist, message_type, param);
2714 /* PORT sends ALERTING message */
2715 case MESSAGE_ALERTING:
2716 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);
2717 if (e_state!=EPOINT_STATE_OUT_SETUP
2718 && e_state!=EPOINT_STATE_OUT_OVERLAP
2719 && e_state!=EPOINT_STATE_OUT_PROCEEDING)
2721 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);
2724 port_alerting(portlist, message_type, param);
2727 /* PORT sends CONNECT message */
2728 case MESSAGE_CONNECT:
2729 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);
2730 if (e_state!=EPOINT_STATE_OUT_SETUP
2731 && e_state!=EPOINT_STATE_OUT_OVERLAP
2732 && e_state!=EPOINT_STATE_OUT_PROCEEDING
2733 && e_state!=EPOINT_STATE_OUT_ALERTING)
2735 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
2738 port_connect(portlist, message_type, param);
2741 /* PORT sends DISCONNECT message */
2742 case MESSAGE_DISCONNECT: /* port is disconnected */
2743 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);
2744 port_disconnect_release(portlist, message_type, param);
2747 /* PORT sends a RELEASE message */
2748 case MESSAGE_RELEASE: /* port releases */
2749 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);
2750 /* portlist is release at port_disconnect_release, thanx Paul */
2751 port_disconnect_release(portlist, message_type, param);
2754 /* PORT sends a TIMEOUT message */
2755 case MESSAGE_TIMEOUT:
2756 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);
2757 port_timeout(portlist, message_type, param);
2758 break; /* release */
2760 /* PORT sends a NOTIFY message */
2761 case MESSAGE_NOTIFY:
2762 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);
2763 port_notify(portlist, message_type, param);
2766 /* PORT sends a SUSPEND message */
2767 case MESSAGE_SUSPEND:
2768 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);
2769 port_suspend(portlist, message_type, param);
2770 break; /* suspend */
2772 /* PORT sends a RESUME message */
2773 case MESSAGE_RESUME:
2774 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);
2775 port_resume(portlist, message_type, param);
2779 kann nach dem test gelöscht werden, da eine direkte funktion im join und im mISDN zum austausch der message existiert
2780 /* port assigns bchannel */
2781 case MESSAGE_BCHANNEL: /* bchannel assignment messafe */
2782 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);
2783 /* only one port is expected to be connected to bchannel */
2784 message = message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2785 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_IN);
2791 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);
2794 /* Note: this endpoint may be destroyed, so we MUST return */
2798 /* messages from join
2800 /* join MESSAGE_CRYPT */
2801 void EndpointAppPBX::join_crypt(struct port_list *portlist, int message_type, union parameter *param)
2803 switch(param->crypt.type)
2805 /* message from remote port to "crypt manager" */
2806 case CU_ACTK_REQ: /* activate key-exchange */
2807 case CU_ACTS_REQ: /* activate shared key */
2808 case CU_DACT_REQ: /* deactivate */
2809 case CU_INFO_REQ: /* request last info message */
2810 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2813 /* message from "crypt manager" to user */
2814 case CU_ACTK_CONF: /* key-echange done */
2815 case CU_ACTS_CONF: /* shared key done */
2816 case CU_DACT_CONF: /* deactivated */
2817 case CU_DACT_IND: /* deactivated */
2818 case CU_ERROR_IND: /* receive error message */
2819 case CU_INFO_IND: /* receive info message */
2820 case CU_INFO_CONF: /* receive info message */
2821 encrypt_result(param->crypt.type, (char *)param->crypt.data);
2825 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);
2829 /* join MESSAGE_INFORMATION */
2830 void EndpointAppPBX::join_information(struct port_list *portlist, int message_type, union parameter *param)
2832 struct lcr_msg *message;
2838 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2839 memcpy(&message->param.information, ¶m->information, sizeof(struct dialing_info));
2840 message_put(message);
2841 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2842 portlist = portlist->next;
2846 /* join MESSAGE_FACILITY */
2847 void EndpointAppPBX::join_facility(struct port_list *portlist, int message_type, union parameter *param)
2849 struct lcr_msg *message;
2851 if (!e_ext.facility && e_ext.number[0])
2858 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_FACILITY);
2859 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2860 message_put(message);
2861 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2862 portlist = portlist->next;
2866 /* join MESSAGE_MORE */
2867 void EndpointAppPBX::join_overlap(struct port_list *portlist, int message_type, union parameter *param)
2869 struct lcr_msg *message;
2871 new_state(EPOINT_STATE_IN_OVERLAP);
2874 if (e_join_pattern && e_ext.own_setup)
2876 /* disconnect audio */
2877 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2878 message->param.audiopath = 0;
2879 message_put(message);
2881 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
2883 if (e_dialinginfo.id[0])
2884 set_tone(portlist, "dialing");
2886 set_tone(portlist, "dialtone");
2889 if (e_ext.number[0])
2890 set_tone(portlist, "dialpbx");
2892 set_tone(portlist, "dialtone");
2895 /* join MESSAGE_PROCEEDING */
2896 void EndpointAppPBX::join_proceeding(struct port_list *portlist, int message_type, union parameter *param)
2898 struct lcr_msg *message;
2900 new_state(EPOINT_STATE_IN_PROCEEDING);
2902 /* own proceeding tone */
2905 /* connect / disconnect audio */
2906 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2907 if (e_ext.own_proceeding)
2908 message->param.audiopath = 0;
2910 message->param.audiopath = 1;
2911 message_put(message);
2913 // UCPY(e_join_tone, "proceeding");
2916 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
2917 message_put(message);
2918 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2920 set_tone(portlist, "proceeding");
2923 /* join MESSAGE_ALERTING */
2924 void EndpointAppPBX::join_alerting(struct port_list *portlist, int message_type, union parameter *param)
2926 struct lcr_msg *message;
2928 new_state(EPOINT_STATE_IN_ALERTING);
2930 /* own alerting tone */
2933 /* connect / disconnect audio */
2934 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2935 if (e_ext.own_alerting)
2936 message->param.audiopath = 0;
2938 message->param.audiopath = 1;
2939 message_put(message);
2943 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
2944 message_put(message);
2945 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2947 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
2949 set_tone(portlist, "ringing");
2952 if (e_ext.number[0])
2953 set_tone(portlist, "ringpbx");
2955 set_tone(portlist, "ringing");
2958 /* join MESSAGE_CONNECT */
2959 void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type, union parameter *param)
2961 struct lcr_msg *message;
2963 new_state(EPOINT_STATE_CONNECT);
2964 // UCPY(e_join_tone, "");
2966 if (e_ext.number[0])
2967 e_dtmf = 1; /* allow dtmf */
2970 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_callerinfo));
2973 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
2974 memcpy(&message->param, param, sizeof(union parameter));
2976 /* screen clip if prefix is required */
2977 if (e_ext.number[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0])
2979 SCPY(message->param.connectinfo.id, e_ext.clip_prefix);
2980 SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype, options.national, options.international));
2981 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2984 /* use internal caller id */
2985 if (e_ext.number[0] && e_connectinfo.extension[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
2987 SCPY(message->param.connectinfo.id, e_connectinfo.extension);
2988 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2991 /* handle restricted caller ids */
2992 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);
2993 /* display callerid if desired for extension */
2994 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));
2996 /* use conp, if enabld */
2997 // if (!e_ext.centrex)
2998 // message->param.connectinfo.name[0] = '\0';
3001 message_put(message);
3002 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3004 set_tone(portlist, NULL);
3006 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3007 message->param.audiopath = 1;
3008 message_put(message);
3012 /* join MESSAGE_DISCONNECT MESSAGE_RELEASE */
3013 void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *param)
3016 struct lcr_msg *message;
3017 struct port_list *portlist = NULL;
3020 /* be sure that we are active */
3022 e_tx_state = NOTIFY_STATE_ACTIVE;
3024 /* we are powerdialing, if e_powerdialing is set and limit is not exceeded if given */
3025 if (e_powerdialing && ((e_powercount+1)<e_powerlimit || e_powerlimit<1))
3027 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
3029 /* set time for power dialing */
3030 e_powerdialing = now_d + e_powerdelay; /* set redial in the future */
3033 /* set redial tone */
3034 if (ea_endpoint->ep_portlist)
3038 set_tone(ea_endpoint->ep_portlist, "redial");
3039 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);
3040 /* send proceeding when powerdialing and still setup (avoid dialing timeout) */
3041 if (e_state==EPOINT_STATE_IN_OVERLAP)
3043 new_state(EPOINT_STATE_IN_PROCEEDING);
3044 if (ea_endpoint->ep_portlist)
3046 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3047 message_put(message);
3048 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3050 /* caused the error, that the first knock sound was not there */
3051 /* set_tone(portlist, "proceeding"); */
3053 /* send display of powerdialing */
3054 if (e_ext.display_dialing)
3056 portlist = ea_endpoint->ep_portlist;
3059 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3061 SPRINT(message->param.notifyinfo.display, "Retry %d of %d", e_powercount, e_powerlimit);
3063 SPRINT(message->param.notifyinfo.display, "Retry %d", e_powercount);
3064 message_put(message);
3065 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3066 portlist = portlist->next;
3075 if ((e_state!=EPOINT_STATE_CONNECT
3076 && e_state!=EPOINT_STATE_OUT_DISCONNECT
3077 && e_state!=EPOINT_STATE_IN_OVERLAP
3078 && e_state!=EPOINT_STATE_IN_PROCEEDING
3079 && e_state!=EPOINT_STATE_IN_ALERTING)
3080 || !ea_endpoint->ep_portlist) /* or no port */
3082 process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
3083 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause); /* RELEASE_TYPE, join, port */
3084 return; /* must exit here */
3089 e_join_cause = param->disconnectinfo.cause;
3090 e_join_location = param->disconnectinfo.location;
3093 /* on release we need the audio again! */
3094 if (message_type == MESSAGE_RELEASE)
3097 ea_endpoint->ep_join_id = 0;
3099 /* disconnect and select tone */
3100 new_state(EPOINT_STATE_OUT_DISCONNECT);
3101 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
3102 /* if own_cause, we must release the join */
3103 if (e_ext.own_cause /* own cause */
3104 || !e_join_pattern) /* no patterns */
3106 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);
3107 if (message_type != MESSAGE_RELEASE)
3108 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
3110 } else /* else we enable audio */
3112 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3113 message->param.audiopath = 1;
3114 message_put(message);
3116 /* send disconnect message */
3117 SCPY(e_tone, cause);
3118 portlist = ea_endpoint->ep_portlist;
3121 set_tone(portlist, cause);
3122 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
3123 portlist = portlist->next;
3127 /* join MESSAGE_SETUP */
3128 void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, union parameter *param)
3130 struct lcr_msg *message;
3131 // struct interface *interface;
3133 /* if we already in setup state, we just update the dialing with new digits */
3134 if (e_state == EPOINT_STATE_OUT_SETUP
3135 || e_state == EPOINT_STATE_OUT_OVERLAP)
3137 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we are in setup state, so we do overlap dialing.\n", ea_endpoint->ep_serial);
3138 /* if digits changed, what we have already dialed */
3139 if (!!strncmp(e_dialinginfo.id,param->setup.dialinginfo.id,strlen(e_dialinginfo.id)))
3141 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);
3142 /* release all ports */
3143 while((portlist = ea_endpoint->ep_portlist))
3145 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
3146 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
3147 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3148 message_put(message);
3149 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3150 ea_endpoint->free_portlist(portlist);
3153 /* disconnect audio */
3154 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3155 message->param.audiopath = 0;
3156 message_put(message);
3158 /* get dialing info */
3159 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3160 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3161 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3162 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3163 new_state(EPOINT_STATE_OUT_OVERLAP);
3166 e_redial = now_d + 1; /* set redial one second in the future */
3169 /* if we have a pending redial, so we just adjust the dialing number */
3172 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);
3173 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3176 if (!ea_endpoint->ep_portlist)
3178 PERROR("ERROR: overlap dialing to a NULL port relation\n");
3180 if (ea_endpoint->ep_portlist->next)
3182 PERROR("ERROR: overlap dialing to a port_list port relation\n");
3184 if (e_state == EPOINT_STATE_OUT_SETUP)
3187 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);
3188 SCAT(e_dialing_queue, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3192 /* get what we have not dialed yet */
3193 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));
3194 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
3195 SCPY(message->param.information.id, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3196 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
3197 message_put(message);
3198 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3200 /* always store what we have dialed or queued */
3201 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3205 if (e_state != EPOINT_STATE_IDLE)
3207 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
3210 /* if an internal extension is dialed, copy that number */
3211 if (param->setup.dialinginfo.itype==INFO_ITYPE_ISDN_EXTENSION || param->setup.dialinginfo.itype==INFO_ITYPE_VBOX)
3212 SCPY(e_ext.number, param->setup.dialinginfo.id);
3213 /* if an internal extension is dialed, get extension's info about caller */
3214 if (e_ext.number[0])
3216 if (!read_extension(&e_ext, e_ext.number))
3218 e_ext.number[0] = '\0';
3219 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the called terminal='%s' is not found in directory tree!\n", ea_endpoint->ep_serial, e_ext.number);
3223 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3224 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3225 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3226 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3228 /* process (voice over) data calls */
3229 if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO)
3231 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) handling data call as audio call: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
3232 memset(&e_capainfo, 0, sizeof(e_capainfo));
3233 e_capainfo.bearer_capa = INFO_BC_AUDIO;
3234 e_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
3235 e_capainfo.bearer_info1 = (options.law=='u')?INFO_INFO1_ULAW:INFO_INFO1_ALAW;
3238 new_state(EPOINT_STATE_OUT_SETUP);
3239 /* call special setup routine */
3243 /* join MESSAGE_mISDNSIGNAL */
3244 void EndpointAppPBX::join_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param)
3246 struct lcr_msg *message;
3250 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
3251 memcpy(&message->param, param, sizeof(union parameter));
3252 message_put(message);
3253 portlist = portlist->next;
3257 /* join MESSAGE_NOTIFY */
3258 void EndpointAppPBX::join_notify(struct port_list *portlist, int message_type, union parameter *param)
3260 struct lcr_msg *message;
3263 if (param->notifyinfo.notify)
3265 new_state = track_notify(e_tx_state, param->notifyinfo.notify);
3266 // /* if notification was generated locally, we turn hold music on/off */
3267 // if (param->notifyinfo.local)
3268 // 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)
3273 if (new_state!=NOTIFY_STATE_HOLD && new_state!=NOTIFY_STATE_SUSPEND)
3275 if (!strcmp(e_tone, "hold")) // don't interrupt other tones
3279 set_tone(portlist, "");
3280 portlist = portlist->next;
3283 portlist = ea_endpoint->ep_portlist;
3288 if (new_state==NOTIFY_STATE_HOLD || new_state==NOTIFY_STATE_SUSPEND)
3292 set_tone(portlist, "hold");
3293 portlist = portlist->next;
3295 portlist = ea_endpoint->ep_portlist;
3300 /* save new state */
3301 e_tx_state = new_state;
3304 /* notify port(s) about it */
3307 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3308 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
3309 /* handle restricted caller ids */
3310 apply_callerid_restriction(&e_ext, message->param.notifyinfo.id, &message->param.notifyinfo.ntype, &message->param.notifyinfo.present, 0, message->param.notifyinfo.extension, NULL);
3311 /* display callerid if desired for extension */
3312 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));
3313 message_put(message);
3314 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3315 portlist = portlist->next;
3319 /* JOIN sends messages to the endpoint
3321 void EndpointAppPBX::ea_message_join(unsigned int join_id, int message_type, union parameter *param)
3323 struct port_list *portlist;
3324 struct lcr_msg *message;
3328 PERROR("EPOINT(%d) error: JOIN == NULL.\n", ea_endpoint->ep_serial);
3332 portlist = ea_endpoint->ep_portlist;
3334 /* send MESSAGE_DATA to port */
3335 if (message_type == MESSAGE_DATA)
3337 if (join_id == ea_endpoint->ep_join_id) // still linked with JOIN
3339 /* skip if no port relation */
3342 /* skip if more than one port relation */
3345 /* forward audio data to port */
3346 message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3351 // 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);
3352 switch(message_type)
3354 /* JOIN SENDS TONE message */
3356 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);
3357 set_tone(portlist, param->tone.name);
3360 /* JOIN SENDS CRYPT message */
3362 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);
3363 join_crypt(portlist, message_type, param);
3366 /* JOIN sends INFORMATION message */
3367 case MESSAGE_INFORMATION:
3368 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);
3369 join_information(portlist, message_type, param);
3372 /* JOIN sends FACILITY message */
3373 case MESSAGE_FACILITY:
3374 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);
3375 join_facility(portlist, message_type, param);
3378 /* JOIN sends OVERLAP message */
3379 case MESSAGE_OVERLAP:
3380 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received 'more info available'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3381 if (e_state!=EPOINT_STATE_IN_SETUP
3382 && e_state!=EPOINT_STATE_IN_OVERLAP)
3384 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3387 join_overlap(portlist, message_type, param);
3390 /* JOIN sends PROCEEDING message */
3391 case MESSAGE_PROCEEDING:
3392 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);
3393 if(e_state!=EPOINT_STATE_IN_OVERLAP)
3395 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3398 join_proceeding(portlist, message_type, param);
3401 /* JOIN sends ALERTING message */
3402 case MESSAGE_ALERTING:
3403 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);
3404 if (e_state!=EPOINT_STATE_IN_OVERLAP
3405 && e_state!=EPOINT_STATE_IN_PROCEEDING)
3407 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state.\n", ea_endpoint->ep_serial);
3410 join_alerting(portlist, message_type, param);
3413 /* JOIN sends CONNECT message */
3414 case MESSAGE_CONNECT:
3415 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);
3416 if (e_state!=EPOINT_STATE_IN_OVERLAP
3417 && e_state!=EPOINT_STATE_IN_PROCEEDING
3418 && e_state!=EPOINT_STATE_IN_ALERTING)
3420 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
3423 join_connect(portlist, message_type, param);
3426 /* JOIN sends DISCONNECT/RELEASE message */
3427 case MESSAGE_DISCONNECT: /* JOIN disconnect */
3428 case MESSAGE_RELEASE: /* JOIN releases */
3429 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);
3430 join_disconnect_release(message_type, param);
3433 /* JOIN sends SETUP message */
3435 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);
3436 join_setup(portlist, message_type, param);
3439 /* JOIN sends special mISDNSIGNAL message */
3440 case MESSAGE_mISDNSIGNAL: /* isdn message to port */
3441 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);
3442 join_mISDNsignal(portlist, message_type, param);
3446 kann nach dem test gelöscht werden, da eine direkte funktion im join und im mISDN zum austausch der message existiert
3447 /* JOIN requests bchannel */
3448 case MESSAGE_BCHANNEL: /* indicates the need of own bchannel access */
3449 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);
3450 /* only one port is expected to be connected to bchannel */
3457 set_tone(portlist, NULL);
3458 message = message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3459 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3463 /* JOIN has pattern available */
3464 case MESSAGE_PATTERN: /* indicating pattern available */
3465 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);
3466 if (!e_join_pattern)
3468 PDEBUG(DEBUG_EPOINT, "-> pattern becomes available\n");
3473 set_tone(portlist, NULL);
3474 portlist = portlist->next;
3476 /* connect our audio tx and rx (blueboxing should be possibe before connect :)*/
3477 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3478 message->param.audiopath = 1;
3479 message_put(message);
3483 /* JOIN has no pattern available */
3484 case MESSAGE_NOPATTERN: /* indicating no pattern available */
3485 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);
3488 PDEBUG(DEBUG_EPOINT, "-> pattern becomes unavailable\n");
3490 /* disconnect our audio tx and rx */
3491 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3492 message->param.audiopath = 0;
3493 message_put(message);
3498 /* JOIN (dunno at the moment) */
3499 case MESSAGE_REMOTE_AUDIO:
3500 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);
3501 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3502 message->param.audiopath = param->channel;
3503 message_put(message);
3507 /* JOIN sends a notify message */
3508 case MESSAGE_NOTIFY:
3509 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);
3510 join_notify(portlist, message_type, param);
3513 /* JOIN wants keypad / dtml */
3514 case MESSAGE_ENABLEKEYPAD:
3515 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);
3518 trace_header("ENABLE KEYPAD", DIRECTION_NONE);
3523 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);
3528 /* pick_join will connect the first incoming call found. the endpoint
3529 * will receivce a MESSAGE_CONNECT.
3531 int match_list(char *list, char *item)
3533 char *end, *next = NULL;
3535 /* no list make matching */
3541 /* eliminate white spaces */
3542 while (*list <= ' ')
3549 /* if end of list is reached, we return */
3550 if (list[0] == '\0')
3552 /* if we have more than one entry (left) */
3553 if ((end = strchr(list, ',')))
3556 next = end = strchr(list, '\0');
3557 while (*(end-1) <= ' ')
3559 /* if string part matches item */
3560 if (!strncmp(list, item, end-list))
3566 void EndpointAppPBX::pick_join(char *extensions)
3568 struct lcr_msg *message;
3569 struct port_list *portlist;
3571 class EndpointAppPBX *eapp, *found;
3573 class JoinPBX *joinpbx;
3574 struct join_relation *relation;
3577 /* find an endpoint that is ringing internally or vbox with higher priority */
3580 eapp = apppbx_first;
3583 if (eapp!=this && ea_endpoint->ep_portlist)
3585 portlist = eapp->ea_endpoint->ep_portlist;
3588 if ((port = find_port_id(portlist->port_id)))
3590 if (port->p_type == PORT_TYPE_VBOX_OUT)
3592 if (match_list(extensions, eapp->e_ext.number))
3599 if ((port->p_type==PORT_TYPE_DSS1_NT_OUT || port->p_type==PORT_TYPE_DSS1_TE_OUT)
3600 && port->p_state==PORT_STATE_OUT_ALERTING)
3601 if (match_list(extensions, eapp->e_ext.number))
3606 portlist = portlist->next;
3614 /* if no endpoint found */
3617 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);
3619 set_tone(ea_endpoint->ep_portlist, "cause_10");
3620 message_disconnect_port(ea_endpoint->ep_portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
3621 new_state(EPOINT_STATE_OUT_DISCONNECT);
3626 if (ea_endpoint->ep_join_id)
3628 PERROR("EPOINT(%d) we already have a join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3631 if (!eapp->ea_endpoint->ep_join_id)
3633 PERROR("EPOINT(%d) ringing endpoint has no join.\n", ea_endpoint->ep_serial);
3636 join = find_join_id(eapp->ea_endpoint->ep_join_id);
3639 PERROR("EPOINT(%d) ringing endpoint's join not found.\n", ea_endpoint->ep_serial);
3642 if (join->j_type != JOIN_TYPE_PBX)
3644 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ringing endpoint's join is not a PBX join, so we must reject.\n", ea_endpoint->ep_serial);
3647 joinpbx = (class JoinPBX *)join;
3648 relation = joinpbx->j_relation;
3651 PERROR("EPOINT(%d) ringing endpoint's join has no relation. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3654 while (relation->epoint_id != eapp->ea_endpoint->ep_serial)
3656 relation = relation->next;
3659 PERROR("EPOINT(%d) ringing endpoint's join has no relation to that join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3664 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found ringing endpoint: %d.\n", ea_endpoint->ep_serial, eapp->ea_endpoint->ep_serial);
3666 if (options.deb & DEBUG_EPOINT)
3668 class Join *debug_c = join_first;
3669 class Endpoint *debug_e = epoint_first;
3670 class Port *debug_p = port_first;
3672 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(before)");
3674 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3677 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3678 debug_c = debug_c->next;
3680 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3683 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3684 debug_e = debug_e->next;
3686 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3689 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld (active)\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3690 debug_p = debug_p->next;
3695 ea_endpoint->ep_join_id = eapp->ea_endpoint->ep_join_id; /* we get the join */
3696 relation->epoint_id = ea_endpoint->ep_serial; /* the join gets us */
3697 eapp->ea_endpoint->ep_join_id = 0; /* the ringing endpoint will get disconnected */
3699 /* connnecting our endpoint */
3700 new_state(EPOINT_STATE_CONNECT);
3701 if (e_ext.number[0])
3703 set_tone(ea_endpoint->ep_portlist, NULL);
3705 /* now we send a release to the ringing endpoint */
3706 message = message_create(ea_endpoint->ep_join_id, eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3707 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
3708 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3709 message_put(message);
3711 /* we send a connect to the join with our caller id */
3712 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CONNECT);
3713 SCPY(message->param.connectinfo.id, e_callerinfo.id);
3714 message->param.connectinfo.present = e_callerinfo.present;
3715 message->param.connectinfo.screen = e_callerinfo.screen;
3716 message->param.connectinfo.itype = e_callerinfo.itype;
3717 message->param.connectinfo.ntype = e_callerinfo.ntype;
3718 message_put(message);
3720 /* we send a connect to our port with the remote callerid */
3721 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3722 SCPY(message->param.connectinfo.id, eapp->e_callerinfo.id);
3723 message->param.connectinfo.present = eapp->e_callerinfo.present;
3724 message->param.connectinfo.screen = eapp->e_callerinfo.screen;
3725 message->param.connectinfo.itype = eapp->e_callerinfo.itype;
3726 message->param.connectinfo.ntype = eapp->e_callerinfo.ntype;
3727 /* handle restricted caller ids */
3728 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);
3729 /* display callerid if desired for extension */
3730 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));
3731 message_put(message);
3733 /* we send a connect to the audio path (not for vbox) */
3734 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3735 message->param.audiopath = 1;
3736 message_put(message);
3738 /* beeing paranoid, we make call update */
3739 joinpbx->j_updatebridge = 1;
3741 if (options.deb & DEBUG_EPOINT)
3743 class Join *debug_c = join_first;
3744 class Endpoint *debug_e = epoint_first;
3745 class Port *debug_p = port_first;
3747 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(after)");
3749 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3752 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3753 debug_c = debug_c->next;
3755 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3758 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3759 debug_e = debug_e->next;
3761 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3764 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3765 debug_p = debug_p->next;
3771 /* join calls (look for a join that is on hold (same isdn interface/terminal))
3773 void EndpointAppPBX::join_join(void)
3775 struct lcr_msg *message;
3776 struct join_relation *our_relation, *other_relation;
3777 struct join_relation **our_relation_pointer, **other_relation_pointer;
3778 class Join *our_join, *other_join;
3779 class JoinPBX *our_joinpbx, *other_joinpbx;
3780 class EndpointAppPBX *other_eapp; class Endpoint *temp_epoint;
3781 class Port *our_port, *other_port;
3782 class Pdss1 *our_pdss1, *other_pdss1;
3784 /* are we a candidate to join a join */
3785 our_join = find_join_id(ea_endpoint->ep_join_id);
3788 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3791 if (our_join->j_type != JOIN_TYPE_PBX)
3793 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: join is not a pbx join.\n", ea_endpoint->ep_serial);
3796 our_joinpbx = (class JoinPBX *)our_join;
3797 if (!ea_endpoint->ep_portlist)
3799 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
3802 if (!e_ext.number[0])
3804 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
3807 our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
3810 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
3813 if ((our_port->p_type&PORT_CLASS_mISDN_MASK) != PORT_CLASS_mISDN_DSS1)
3815 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not isdn.\n", ea_endpoint->ep_serial);
3818 our_pdss1 = (class Pdss1 *)our_port;
3820 /* find an endpoint that is on hold and has the same mISDNport that we are on */
3821 other_eapp = apppbx_first;
3824 if (other_eapp == this)
3826 other_eapp = other_eapp->next;
3829 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);
3830 if (other_eapp->e_ext.number[0] /* has terminal */
3831 && other_eapp->ea_endpoint->ep_portlist /* has port */
3832 && other_eapp->ea_endpoint->ep_join_id) /* has join */
3834 other_port = find_port_id(other_eapp->ea_endpoint->ep_portlist->port_id);
3835 if (other_port) /* port still exists */
3837 if (other_port->p_type==PORT_TYPE_DSS1_NT_OUT
3838 || other_port->p_type==PORT_TYPE_DSS1_NT_IN) /* port is isdn nt-mode */
3840 other_pdss1 = (class Pdss1 *)other_port;
3841 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);
3842 if (other_pdss1->p_m_hold /* port is on hold */
3843 && other_pdss1->p_m_mISDNport == our_pdss1->p_m_mISDNport /* same isdn interface */
3844 && other_pdss1->p_m_d_ces == our_pdss1->p_m_d_ces) /* same tei+sapi */
3848 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of other type!\n", ea_endpoint->ep_serial);
3852 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port doesn't exist enymore.\n", ea_endpoint->ep_serial);
3855 other_eapp = other_eapp->next;
3859 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn interface with port on hold.\n", ea_endpoint->ep_serial);
3862 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port on hold found.\n", ea_endpoint->ep_serial);
3864 /* if we have the same join */
3865 if (other_eapp->ea_endpoint->ep_join_id == ea_endpoint->ep_join_id)
3867 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we an the other have the same join.\n", ea_endpoint->ep_serial);
3870 other_join = find_join_id(other_eapp->ea_endpoint->ep_join_id);
3873 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3876 if (other_join->j_type != JOIN_TYPE_PBX)
3878 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join is not a pbx join.\n", ea_endpoint->ep_serial);
3881 other_joinpbx = (class JoinPBX *)other_join;
3882 if (our_joinpbx->j_partyline && other_joinpbx->j_partyline)
3884 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both joins are partylines.\n", ea_endpoint->ep_serial);
3888 /* remove relation to endpoint for join on hold */
3889 other_relation = other_joinpbx->j_relation;
3890 other_relation_pointer = &other_joinpbx->j_relation;
3891 while(other_relation)
3893 if (other_relation->epoint_id == other_eapp->ea_endpoint->ep_serial)
3895 /* detach other endpoint on hold */
3896 *other_relation_pointer = other_relation->next;
3897 FREE(other_relation, sizeof(struct join_relation));
3899 other_relation = *other_relation_pointer;
3900 other_eapp->ea_endpoint->ep_join_id = 0;
3904 /* change join/hold pointer of endpoint to the new join */
3905 temp_epoint = find_epoint_id(other_relation->epoint_id);
3908 if (temp_epoint->ep_join_id == other_join->j_serial)
3909 temp_epoint->ep_join_id = our_join->j_serial;
3912 other_relation_pointer = &other_relation->next;
3913 other_relation = other_relation->next;
3915 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint on hold removed, other enpoints on join relinked (to our join).\n", ea_endpoint->ep_serial);
3917 /* join call relations */
3918 our_relation = our_joinpbx->j_relation;
3919 our_relation_pointer = &our_joinpbx->j_relation;
3922 our_relation_pointer = &our_relation->next;
3923 our_relation = our_relation->next;
3925 *our_relation_pointer = other_joinpbx->j_relation;
3926 other_joinpbx->j_relation = NULL;
3927 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) relations joined.\n", ea_endpoint->ep_serial);
3929 /* release endpoint on hold */
3930 message = message_create(other_joinpbx->j_serial, other_eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3931 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */
3932 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3933 message_put(message);
3935 /* if we are not a partyline, we get partyline state from other join */
3936 our_joinpbx->j_partyline += other_joinpbx->j_partyline;
3938 /* remove empty join */
3940 PDEBUG(DEBUG_EPOINT, "EPOINT(%d)d-join completely removed!\n");
3942 /* mixer must update */
3943 our_joinpbx->j_updatebridge = 1; /* update mixer flag */
3945 /* we send a retrieve to that endpoint */
3946 // mixer will update the hold-state of the join and send it to the endpoints is changes
3950 /* check if we have an external call
3951 * this is used to check for encryption ability
3953 int EndpointAppPBX::check_external(char **errstr, class Port **port)
3955 struct join_relation *relation;
3957 class JoinPBX *joinpbx;
3958 class Endpoint *epoint;
3960 /* some paranoia check */
3961 if (!ea_endpoint->ep_portlist)
3963 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we have no port.\n", ea_endpoint->ep_serial);
3964 *errstr = "No Call";
3967 if (!e_ext.number[0])
3969 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we are not internal extension.\n", ea_endpoint->ep_serial);
3970 *errstr = "No Call";
3974 /* check if we have a join with 2 parties */
3975 join = find_join_id(ea_endpoint->ep_join_id);
3978 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have currently no join.\n", ea_endpoint->ep_serial);
3979 *errstr = "No Call";
3982 if (join->j_type != JOIN_TYPE_PBX)
3984 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join is not a pbx join.\n", ea_endpoint->ep_serial);
3985 *errstr = "No PBX Call";
3988 joinpbx = (class JoinPBX *)join;
3989 relation = joinpbx->j_relation;
3992 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no relation.\n", ea_endpoint->ep_serial);
3993 *errstr = "No Call";
3996 if (!relation->next)
3998 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd relation.\n", ea_endpoint->ep_serial);
3999 *errstr = "No Call";
4002 if (relation->next->next)
4004 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has more than two relations.\n", ea_endpoint->ep_serial);
4005 *errstr = "Err: Conference";
4008 if (relation->epoint_id == ea_endpoint->ep_serial)
4010 relation = relation->next;
4011 if (relation->epoint_id == ea_endpoint->ep_serial)
4013 PERROR("EPOINT(%d) SOFTWARE ERROR: both join relations are related to our endpoint.\n", ea_endpoint->ep_serial);
4014 *errstr = "Software Error";
4019 /* check remote port for external call */
4020 epoint = find_epoint_id(relation->epoint_id);
4023 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd endpoint.\n", ea_endpoint->ep_serial);
4024 *errstr = "No Call";
4027 if (!epoint->ep_portlist)
4029 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not port.\n", ea_endpoint->ep_serial);
4030 *errstr = "No Call";
4033 *port = find_port_id(epoint->ep_portlist->port_id);
4036 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has an none existing port.\n", ea_endpoint->ep_serial);
4037 *errstr = "No Call";
4040 if (((*port)->p_type&PORT_CLASS_mISDN_MASK)!=PORT_CLASS_mISDN_DSS1) /* port is not external isdn */
4042 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not an external port.\n", ea_endpoint->ep_serial);
4043 *errstr = "No Ext Call";
4046 if ((*port)->p_state != PORT_STATE_CONNECT)
4048 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint's port is not in connected state.\n", ea_endpoint->ep_serial);
4049 *errstr = "No Ext Connect";
4055 void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsigned int port_id, int dir)
4057 char *logtext = "unknown";
4060 switch(message_type)
4063 trace_header("SETUP", dir);
4064 if (dir == DIRECTION_OUT)
4065 add_trace("to", NULL, "CH(%lu)", port_id);
4066 if (dir == DIRECTION_IN)
4067 add_trace("from", NULL, "CH(%lu)", port_id);
4068 if (param->setup.callerinfo.extension[0])
4069 add_trace("extension", NULL, "%s", param->setup.callerinfo.extension);
4070 add_trace("caller id", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype, options.national, options.international));
4071 switch(param->setup.callerinfo.present)
4073 case INFO_PRESENT_RESTRICTED:
4074 add_trace("caller id", "present", "restricted");
4076 case INFO_PRESENT_ALLOWED:
4077 add_trace("caller id", "present", "allowed");
4080 add_trace("caller id", "present", "not available");
4082 if (param->setup.redirinfo.id[0])
4084 add_trace("redir'ing", "number", "%s", numberrize_callerinfo(param->setup.redirinfo.id, param->setup.redirinfo.ntype, options.national, options.international));
4085 switch(param->setup.redirinfo.present)
4087 case INFO_PRESENT_RESTRICTED:
4088 add_trace("redir'ing", "present", "restricted");
4090 case INFO_PRESENT_ALLOWED:
4091 add_trace("redir'ing", "present", "allowed");
4094 add_trace("redir'ing", "present", "not available");
4097 if (param->setup.dialinginfo.id[0])
4098 add_trace("dialing", NULL, "%s", param->setup.dialinginfo.id);
4102 case MESSAGE_OVERLAP:
4103 trace_header("SETUP ACKNOWLEDGE", dir);
4104 if (dir == DIRECTION_OUT)
4105 add_trace("to", NULL, "CH(%lu)", port_id);
4106 if (dir == DIRECTION_IN)
4107 add_trace("from", NULL, "CH(%lu)", port_id);
4111 case MESSAGE_PROCEEDING:
4112 trace_header("PROCEEDING", dir);
4113 if (dir == DIRECTION_OUT)
4114 add_trace("to", NULL, "CH(%lu)", port_id);
4115 if (dir == DIRECTION_IN)
4116 add_trace("from", NULL, "CH(%lu)", port_id);
4120 case MESSAGE_ALERTING:
4121 trace_header("ALERTING", dir);
4122 if (dir == DIRECTION_OUT)
4123 add_trace("to", NULL, "CH(%lu)", port_id);
4124 if (dir == DIRECTION_IN)
4125 add_trace("from", NULL, "CH(%lu)", port_id);
4129 case MESSAGE_CONNECT:
4130 trace_header("CONNECT", dir);
4131 if (dir == DIRECTION_OUT)
4132 add_trace("to", NULL, "CH(%lu)", port_id);
4133 if (dir == DIRECTION_IN)
4134 add_trace("from", NULL, "CH(%lu)", port_id);
4135 if (param->connectinfo.extension[0])
4136 add_trace("extension", NULL, "%s", param->connectinfo.extension);
4137 add_trace("connect id", "number", "%s", numberrize_callerinfo(param->connectinfo.id, param->connectinfo.ntype, options.national, options.international));
4138 switch(param->connectinfo.present)
4140 case INFO_PRESENT_RESTRICTED:
4141 add_trace("connect id", "present", "restricted");
4143 case INFO_PRESENT_ALLOWED:
4144 add_trace("connect id", "present", "allowed");
4147 add_trace("connect id", "present", "not available");
4152 case MESSAGE_DISCONNECT:
4153 case MESSAGE_RELEASE:
4154 if (message_type == MESSAGE_DISCONNECT)
4155 trace_header("DISCONNECT", dir);
4157 trace_header("RELEASE", dir);
4158 if (dir == DIRECTION_OUT)
4159 add_trace("to", NULL, "CH(%lu)", port_id);
4160 if (dir == DIRECTION_IN)
4161 add_trace("from", NULL, "CH(%lu)", port_id);
4162 add_trace("cause", "value", "%d", param->disconnectinfo.cause);
4163 switch(param->disconnectinfo.location)
4166 add_trace("cause", "location", "0-User");
4168 case LOCATION_PRIVATE_LOCAL:
4169 add_trace("cause", "location", "1-Local-PBX");
4171 case LOCATION_PUBLIC_LOCAL:
4172 add_trace("cause", "location", "2-Local-Exchange");
4174 case LOCATION_TRANSIT:
4175 add_trace("cause", "location", "3-Transit");
4177 case LOCATION_PUBLIC_REMOTE:
4178 add_trace("cause", "location", "4-Remote-Exchange");
4180 case LOCATION_PRIVATE_REMOTE:
4181 add_trace("cause", "location", "5-Remote-PBX");
4183 case LOCATION_INTERNATIONAL:
4184 add_trace("cause", "location", "7-International-Exchange");
4186 case LOCATION_BEYOND:
4187 add_trace("cause", "location", "10-Beyond-Interworking");
4190 add_trace("cause", "location", "%d", param->disconnectinfo.location);
4195 case MESSAGE_NOTIFY:
4196 switch(param->notifyinfo.notify)
4202 logtext = "USER_SUSPENDED";
4205 logtext = "BEARER_SERVICE_CHANGED";
4208 logtext = "USER_RESUMED";
4211 logtext = "CONFERENCE_ESTABLISHED";
4214 logtext = "CONFERENCE_DISCONNECTED";
4217 logtext = "OTHER_PARTY_ADDED";
4220 logtext = "ISOLATED";
4223 logtext = "REATTACHED";
4226 logtext = "OTHER_PARTY_ISOLATED";
4229 logtext = "OTHER_PARTY_REATTACHED";
4232 logtext = "OTHER_PARTY_SPLIT";
4235 logtext = "OTHER_PARTY_DISCONNECTED";
4238 logtext = "CONFERENCE_FLOATING";
4241 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
4244 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
4247 logtext = "CALL_IS_A_WAITING_CALL";
4250 logtext = "DIVERSION_ACTIVATED";
4253 logtext = "RESERVED_CT_1";
4256 logtext = "RESERVED_CT_2";
4259 logtext = "REVERSE_CHARGING";
4262 logtext = "REMOTE_HOLD";
4265 logtext = "REMOTE_RETRIEVAL";
4268 logtext = "CALL_IS_DIVERTING";
4271 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
4275 trace_header("NOTIFY", dir);
4276 if (dir == DIRECTION_OUT)
4277 add_trace("to", NULL, "CH(%lu)", port_id);
4278 if (dir == DIRECTION_IN)
4279 add_trace("from", NULL, "CH(%lu)", port_id);
4280 if (param->notifyinfo.notify)
4281 add_trace("indicator", NULL, "%s", logtext);
4282 if (param->notifyinfo.id[0])
4284 add_trace("redir'on", "number", "%s", numberrize_callerinfo(param->notifyinfo.id, param->notifyinfo.ntype, options.national, options.international));
4285 switch(param->notifyinfo.present)
4287 case INFO_PRESENT_RESTRICTED:
4288 add_trace("redir'on", "present", "restricted");
4290 case INFO_PRESENT_ALLOWED:
4291 add_trace("redir'on", "present", "allowed");
4294 add_trace("redir'on", "present", "not available");
4297 if (param->notifyinfo.display[0])
4298 add_trace("display", NULL, "%s", param->notifyinfo.display);
4302 case MESSAGE_INFORMATION:
4303 trace_header("INFORMATION", dir);
4304 if (dir == DIRECTION_OUT)
4305 add_trace("to", NULL, "CH(%lu)", port_id);
4306 if (dir == DIRECTION_IN)
4307 add_trace("from", NULL, "CH(%lu)", port_id);
4308 add_trace("dialing", NULL, "%s", param->information.id);
4312 case MESSAGE_FACILITY:
4313 trace_header("FACILITY", dir);
4314 if (dir == DIRECTION_OUT)
4315 add_trace("to", NULL, "CH(%lu)", port_id);
4316 if (dir == DIRECTION_IN)
4317 add_trace("from", NULL, "CH(%lu)", port_id);
4322 trace_header("TONE", dir);
4323 if (dir == DIRECTION_OUT)
4324 add_trace("to", NULL, "CH(%lu)", port_id);
4325 if (dir == DIRECTION_IN)
4326 add_trace("from", NULL, "CH(%lu)", port_id);
4327 if (param->tone.name[0])
4329 add_trace("directory", NULL, "%s", param->tone.dir[0]?param->tone.dir:"default");
4330 add_trace("name", NULL, "%s", param->tone.name);
4332 add_trace("off", NULL, NULL);
4336 case MESSAGE_SUSPEND:
4337 case MESSAGE_RESUME:
4338 if (message_type == MESSAGE_SUSPEND)
4339 trace_header("SUSPEND", dir);
4341 trace_header("RESUME", dir);
4342 if (dir == DIRECTION_OUT)
4343 add_trace("to", NULL, "CH(%lu)", port_id);
4344 if (dir == DIRECTION_IN)
4345 add_trace("from", NULL, "CH(%lu)", port_id);
4346 if (param->parkinfo.len)
4347 add_trace("length", NULL, "%d", param->parkinfo.len);
4352 case MESSAGE_BCHANNEL:
4353 trace_header("BCHANNEL", dir);
4354 switch(param->bchannel.type)
4356 case BCHANNEL_REQUEST:
4357 add_trace("type", NULL, "request");
4359 case BCHANNEL_ASSIGN:
4360 add_trace("type", NULL, "assign");
4362 case BCHANNEL_ASSIGN_ACK:
4363 add_trace("type", NULL, "assign_ack");
4365 case BCHANNEL_REMOVE:
4366 add_trace("type", NULL, "remove");
4368 case BCHANNEL_REMOVE_ACK:
4369 add_trace("type", NULL, "remove_ack");
4372 if (param->bchannel.addr)
4373 add_trace("address", NULL, "%x", param->bchannel.addr);
4379 PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message_type);
4383 void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cause, int location, char *display)
4385 struct lcr_msg *message;
4389 if (!portlist->port_id)
4392 if (!e_connectedmode)
4394 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT);
4395 message->param.disconnectinfo.cause = cause;
4396 message->param.disconnectinfo.location = location;
4398 SCPY(message->param.disconnectinfo.display, display);
4400 SCPY(message->param.disconnectinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4403 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
4405 SCPY(message->param.notifyinfo.display, display);
4407 SCPY(message->param.notifyinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4409 message_put(message);
4410 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);