1 /*****************************************************************************\
3 ** Linux Call Router **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
8 ** The EndpointAppPBX implements PBX4Linux **
10 \*****************************************************************************/
15 class EndpointAppPBX *apppbx_first = NULL;
18 * EndpointAppPBX constructor
20 EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint, int origin) : EndpointApp(epoint, origin)
22 class EndpointAppPBX **apppointer;
24 /* add application to chain */
26 apppointer = &apppbx_first;
28 apppointer = &((*apppointer)->next);
32 memset(&e_ext, 0, sizeof(struct extension));
33 // *************** NOTE: also change value in read_extension() **************
34 e_ext.rights = 4; /* international */
35 e_ext.rx_gain = e_ext.tx_gain = 0;
36 e_state = EPOINT_STATE_IDLE;
37 e_ext.number[0] = '\0';
38 e_extension_interface[0] = '\0';
39 memset(&e_callerinfo, 0, sizeof(struct caller_info));
40 memset(&e_dialinginfo, 0, sizeof(struct dialing_info));
41 memset(&e_connectinfo, 0, sizeof(struct connect_info));
42 memset(&e_redirinfo, 0, sizeof(struct redir_info));
43 memset(&e_capainfo, 0, sizeof(struct capa_info));
46 e_ruleset = ruleset_main;
48 e_rule = e_ruleset->rule_first;
53 e_match_to_action = NULL;
55 e_extdialing = e_dialinginfo.id;
59 // e_join_tone[0] = e_hold_tone[0] = '\0';
60 e_join_pattern /*= e_hold_pattern*/ = 0;
63 e_adminid = 0; // will be set, if call was initiated via admin socket
68 e_cbdialing[0] = '\0';
71 memset(&e_callbackinfo, 0, sizeof(struct caller_info));
79 e_password_timeout = 0;
80 e_multipoint_cause = 0;
81 e_multipoint_location = 0;
82 e_dialing_queue[0] = '\0';
84 e_crypt_state = CM_ST_NULL;
85 e_crypt_keyengine_busy = 0;
86 e_crypt_info[0] = '\0';
89 e_tx_state = NOTIFY_STATE_ACTIVE;
90 e_rx_state = NOTIFY_STATE_ACTIVE;
91 e_join_cause = e_join_location = 0;
92 /*********************************
93 *********************************
94 ********* ATTENTION *************
95 *********************************
96 *********************************/
97 /* if you add new values, that must be initialized, also check if they must
98 * be initialized when doing callback
104 * EpointAppPBX destructor
106 EndpointAppPBX::~EndpointAppPBX(void)
108 class EndpointAppPBX *temp, **tempp;
112 tempp = &apppbx_first;
122 FATAL("Endpoint not in endpoint's list.\n");
129 * trace header for application
131 void EndpointAppPBX::trace_header(const char *name, int direction)
135 char msgtext[sizeof(_trace.name)];
139 /* init trace with given values */
142 numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype, options.national, options.international),
146 ea_endpoint->ep_serial,
153 /* set new endpoint state
155 void EndpointAppPBX::new_state(int state)
158 if (e_state != state)
160 trace_header("NEW STATE", DIRECTION_NONE);
161 add_trace("state", "old", "%s", state_name[e_state]);
162 add_trace("state", "new", "%s", state_name[state]);
170 /* release join and port (as specified)
172 void EndpointAppPBX::release(int release, int joinlocation, int joincause, int portlocation, int portcause)
174 struct port_list *portlist;
175 struct lcr_msg *message;
178 /* message to test call */
179 admin_call_response(e_adminid, ADMIN_CALL_RELEASE, "", joincause, joinlocation, 0);
181 /* if a release is pending */
182 if (release==RELEASE_JOIN || release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY)
184 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): do pending release (joincause %d location %d)\n", ea_endpoint->ep_serial, joincause, joinlocation);
185 if (ea_endpoint->ep_join_id)
187 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_RELEASE);
188 message->param.disconnectinfo.cause = joincause;
189 message->param.disconnectinfo.location = joinlocation;
190 message_put(message);
191 ea_endpoint->ep_join_id = 0;
195 if (release != RELEASE_PORT_JOINONLY)
198 join_release(e_hold_id, ea_endpoint->ep_serial, 1, joinlocation, joincause);
203 if (release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY)
205 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release (portcause %d portlocation)\n", ea_endpoint->ep_serial, portcause, portlocation);
206 while((portlist = ea_endpoint->ep_portlist))
208 if (portlist->port_id)
210 SPRINT(cause, "cause_%02x", portcause);
211 set_tone(portlist, cause);
212 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
213 message->param.disconnectinfo.cause = portcause;
214 message->param.disconnectinfo.location = portlocation;
215 message_put(message);
216 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
218 ea_endpoint->free_portlist(portlist);
221 /* if callback is enabled, call back with the given caller id */
224 /* reset some stuff */
225 new_state(EPOINT_STATE_IDLE);
226 memset(&e_connectinfo, 0, sizeof(struct connect_info));
227 memset(&e_redirinfo, 0, sizeof(struct redir_info));
228 e_start = e_stop = 0;
229 e_ruleset = ruleset_main;
231 e_rule = e_ruleset->rule_first;
233 e_action_timeout = 0;
235 e_match_to_action = NULL;
237 e_extdialing = e_dialinginfo.id;
245 e_multipoint_cause = 0;
246 e_multipoint_location = 0;
247 e_dialing_queue[0] = '\0';
249 e_crypt_state = CM_ST_NULL;
250 e_crypt_keyengine_busy = 0;
251 e_crypt_info[0] = '\0';
255 e_tx_state = NOTIFY_STATE_ACTIVE;
256 e_rx_state = NOTIFY_STATE_ACTIVE;
257 e_join_cause = e_join_location = 0;
259 /* the caller info of the callback user */
260 memcpy(&e_callbackinfo, &e_callerinfo, sizeof(e_callbackinfo));
261 memset(&e_dialinginfo, 0, sizeof(e_dialinginfo));
262 /* create dialing by callerinfo */
263 if (e_ext.number[0] && e_extension_interface[0])
265 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to internal: %s interface %s\n", ea_endpoint->ep_serial, e_ext.number, e_extension_interface);
266 /* create callback to the current terminal */
267 SCPY(e_dialinginfo.id, e_ext.number);
268 SCPY(e_dialinginfo.interfaces, e_extension_interface);
269 e_dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
270 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
275 SCPY(e_dialinginfo.id, e_cbto);
278 /* numberrize caller id and use it to dial to the callback */
279 SCPY(e_dialinginfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype, options.national, options.international));
281 e_dialinginfo.itype = INFO_ITYPE_ISDN;
282 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
283 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to external: %s\n", ea_endpoint->ep_serial, e_dialinginfo.id);
288 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release of epoint itself.\n", ea_endpoint->ep_serial);
289 ea_endpoint->ep_use--; /* when e_lock is 0, the endpoint will be deleted */
295 /* cancel callerid if restricted, unless anon-ignore is enabled at extension or port is of type external (so called police gets caller id :)*/
296 void apply_callerid_restriction(struct extension *ext, char *id, int *ntype, int *present, int *screen, char *extension, char *name)
298 PDEBUG(DEBUG_EPOINT, "id='%s' ntype=%d present=%d screen=%d extension='%s' name='%s'\n", (id)?id:"NULL", (ntype)?*ntype:-1, (present)?*present:-1, (screen)?*screen:-1, (extension)?extension:"NULL", (name)?name:"NULL");
300 /* caller id is not restricted, so we do nothing */
301 if (*present != INFO_PRESENT_RESTRICTED)
304 /* only extensions are restricted */
308 /* if we enabled anonymouse ignore */
309 if (ext->anon_ignore)
312 /* else we remove the caller id */
316 *ntype = INFO_NTYPE_UNKNOWN;
318 // *screen = INFO_SCREEN_USER;
319 // maybe we should not make voip address anonymous
322 // maybe it's no fraud to present extension id
324 // extension[0] = '\0';
329 /* used display message to display callerid as available */
330 char *EndpointAppPBX::apply_callerid_display(const char *id, int itype, int ntype, int present, int screen, const char *extension, const char *name)
332 static char display[81];
335 const char *cid = numberrize_callerinfo(id, ntype, options.national, options.international);
337 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) id='%s' itype=%d ntype=%d present=%d screen=%d extension='%s' name='%s'\n", ea_endpoint->ep_serial, (id)?id:"NULL", itype, ntype, present, screen, (extension)?extension:"NULL", (name)?name:"NULL");
346 /* NOTE: is caller is is not available for this extesion, it has been removed by apply_callerid_restriction already */
348 /* internal extension's caller id */
349 if (extension[0] && e_ext.display_int)
352 SCAT(display, extension);
355 if (itype == INFO_ITYPE_VBOX)
356 SCAT(display, "(vbox)");
358 SCAT(display, "(int)");
361 /* external caller id */
362 if (!extension[0] && e_ext.display_ext)
368 if (present == INFO_PRESENT_RESTRICTED)
369 SCAT(display, "anonymous");
371 SCAT(display, "unknown");
378 /* display if callerid is anonymouse but available due anon-ignore */
379 if (e_ext.display_anon && present==INFO_PRESENT_RESTRICTED)
382 SCAT(display, "unknown");
385 SCAT(display, " anon");
388 /* display if callerid is anonymouse but available due anon-ignore */
389 if (e_ext.display_fake && screen==INFO_SCREEN_USER && 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, const char *tone)
533 struct lcr_msg *message;
538 /* store for suspended processes */
542 if (e_join_pattern /* pattern are provided */
543 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_SETUP)
544 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_OVERLAP)
545 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_IN_PROCEEDING)
546 && !(e_ext.own_alerting && e_state == EPOINT_STATE_IN_ALERTING)
547 && !(e_ext.own_cause && e_state == EPOINT_STATE_IN_DISCONNECT)
548 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_SETUP)
549 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_OVERLAP)
550 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_OUT_PROCEEDING)
551 && !(e_ext.own_alerting && e_state == EPOINT_STATE_OUT_ALERTING)
552 && !(e_ext.own_cause && e_state == EPOINT_STATE_OUT_DISCONNECT)
553 && tone[0] && !!strncmp(tone,"crypt_*",6))
555 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) tone not provided since patterns are available\n", ea_endpoint->ep_serial);
561 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_TONE);
562 SCPY(message->param.tone.dir, e_ext.tones_dir[0]?e_ext.tones_dir:options.tones_dir);
563 SCPY(message->param.tone.name, tone);
564 message_put(message);
565 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
568 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port to notify tone.\n", ea_endpoint->ep_serial);
575 * hunts an mISDNport that is available for an outgoing call
576 * if no ifname was given, any interface that is not an extension
579 struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel)
581 struct interface *interface;
582 struct interface_port *ifport, *ifport_start;
583 struct select_channel *selchannel;
584 struct mISDNport *mISDNport;
587 interface = interface_first;
589 /* first find the given interface or, if not given, one with no extension */
594 /* check for given interface */
597 if (!strcasecmp(interface->name, ifname))
599 /* found explicit interface */
600 trace_header("CHANNEL SELECTION (found interface)", DIRECTION_NONE);
601 add_trace("interface", NULL, "%s", ifname);
608 if (!interface->extension)
610 /* found non extension */
611 trace_header("CHANNEL SELECTION (found non extension interface)", DIRECTION_NONE);
612 add_trace("interface", NULL, "%s", interface->name);
618 interface = interface->next;
622 /* see if interface has ports */
623 if (!interface->ifport)
626 trace_header("CHANNEL SELECTION (active ports, skipping)", DIRECTION_NONE);
627 add_trace("interface", NULL, "%s", interface->name);
629 interface = interface->next;
633 /* select port by algorithm */
634 ifport_start = interface->ifport;
636 if (interface->hunt == HUNT_ROUNDROBIN)
638 while(ifport_start->next && index<interface->hunt_next)
640 ifport_start = ifport_start->next;
643 trace_header("CHANNEL SELECTION (starting round-robin)", DIRECTION_NONE);
644 add_trace("port", NULL, "%d", ifport_start->portnum);
645 add_trace("position", NULL, "%d", index);
650 ifport = ifport_start;
653 /* see if port is available */
654 if (!ifport->mISDNport)
656 trace_header("CHANNEL SELECTION (port not available, skipping)", DIRECTION_NONE);
657 add_trace("port", NULL, "%d", ifport->portnum);
658 add_trace("position", NULL, "%d", index);
662 mISDNport = ifport->mISDNport;
664 /* see if port is administratively blocked */
667 trace_header("CHANNEL SELECTION (port blocked by admin, skipping)", DIRECTION_NONE);
668 add_trace("port", NULL, "%d", ifport->portnum);
669 add_trace("position", NULL, "%d", index);
674 /* see if link is up on PTP*/
675 if (mISDNport->l2hold && mISDNport->l2link<1)
677 trace_header("CHANNEL SELECTION (port's layer 2 is down, skipping)", DIRECTION_NONE);
678 add_trace("port", NULL, "%d", ifport->portnum);
679 add_trace("position", NULL, "%d", index);
684 /* check for channel form selection list */
686 selchannel = ifport->out_channel;
689 switch(selchannel->channel)
691 case CHANNEL_FREE: /* free channel */
692 if (mISDNport->b_reserved >= mISDNport->b_num)
693 break; /* all channel in use or reserverd */
696 while(i < mISDNport->b_num)
698 if (mISDNport->b_port[i] == NULL)
700 *channel = i+1+(i>=15);
701 trace_header("CHANNEL SELECTION (selecting free channel)", DIRECTION_NONE);
702 add_trace("port", NULL, "%d", ifport->portnum);
703 add_trace("position", NULL, "%d", index);
704 add_trace("channel", NULL, "%d", *channel);
712 trace_header("CHANNEL SELECTION (no channel is 'free')", DIRECTION_NONE);
713 add_trace("port", NULL, "%d", ifport->portnum);
714 add_trace("position", NULL, "%d", index);
718 case CHANNEL_ANY: /* don't ask for channel */
719 if (mISDNport->b_reserved >= mISDNport->b_num)
721 trace_header("CHANNEL SELECTION (cannot ask for 'any' channel, all reserved)", DIRECTION_NONE);
722 add_trace("port", NULL, "%d", ifport->portnum);
723 add_trace("position", NULL, "%d", index);
724 add_trace("total", NULL, "%d", mISDNport->b_num);
725 add_trace("reserved", NULL, "%d", mISDNport->b_reserved);
727 break; /* all channel in use or reserverd */
729 trace_header("CHANNEL SELECTION (using 'any' channel)", DIRECTION_NONE);
730 add_trace("port", NULL, "%d", ifport->portnum);
731 add_trace("position", NULL, "%d", index);
733 *channel = CHANNEL_ANY;
736 case CHANNEL_NO: /* call waiting */
737 trace_header("CHANNEL SELECTION (using 'no' channel, call-waiting)", DIRECTION_NONE);
738 add_trace("port", NULL, "%d", ifport->portnum);
739 add_trace("position", NULL, "%d", index);
741 *channel = CHANNEL_NO;
745 if (selchannel->channel<1 || selchannel->channel==16)
747 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
748 add_trace("port", NULL, "%d", ifport->portnum);
749 add_trace("position", NULL, "%d", index);
750 add_trace("channel", NULL, "%d", selchannel->channel);
752 break; /* invalid channels */
754 i = selchannel->channel-1-(selchannel->channel>=17);
755 if (i >= mISDNport->b_num)
757 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
758 add_trace("port", NULL, "%d", ifport->portnum);
759 add_trace("position", NULL, "%d", index);
760 add_trace("channel", NULL, "%d", selchannel->channel);
761 add_trace("channels", NULL, "%d", mISDNport->b_num);
763 break; /* channel not in port */
765 if (mISDNport->b_port[i] == NULL)
767 *channel = selchannel->channel;
768 trace_header("CHANNEL SELECTION (selecting given channel)", DIRECTION_NONE);
769 add_trace("port", NULL, "%d", ifport->portnum);
770 add_trace("position", NULL, "%d", index);
771 add_trace("channel", NULL, "%d", *channel);
778 break; /* found channel */
779 selchannel = selchannel->next;
782 /* if channel was found, return mISDNport and channel */
785 /* setting next port to start next time */
786 if (interface->hunt == HUNT_ROUNDROBIN)
791 interface->hunt_next = index;
797 trace_header("CHANNEL SELECTION (skipping, no channel found)", DIRECTION_NONE);
798 add_trace("port", NULL, "%d", ifport->portnum);
799 add_trace("position", NULL, "%d", index);
803 /* go next port, until all ports are checked */
805 ifport = ifport->next;
809 ifport = interface->ifport;
811 if (ifport != ifport_start)
815 interface = interface->next;
819 return(NULL); /* no port found */
822 /* outgoing setup to port(s)
823 * ports will be created and a setup is sent if everything is ok. otherwhise
824 * the endpoint is destroyed.
826 void EndpointAppPBX::out_setup(void)
828 struct dialing_info dialinginfo;
830 // 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;
848 int mode = B_MODE_TRANSPARENT;
850 /* set bchannel mode */
851 mode = e_capainfo.source_mode;
853 /* create settings for creating port */
854 memset(&port_settings, 0, sizeof(port_settings));
856 SCPY(port_settings.tones_dir, e_ext.tones_dir);
858 SCPY(port_settings.tones_dir, options.tones_dir);
859 port_settings.no_seconds = e_ext.no_seconds;
861 /* 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 */
863 /* check what dialinginfo.itype we got */
864 switch(e_dialinginfo.itype)
866 /* *********************** call to extension or vbox */
867 case INFO_ITYPE_ISDN_EXTENSION:
868 /* check if we deny incoming calls when we use an extension */
869 if (e_ext.noknocking)
871 atemp = apppbx_first;
875 if (!strcmp(atemp->e_ext.number, e_ext.number))
881 PERROR("EPOINT(%d) noknocking and currently a call\n", ea_endpoint->ep_serial);
882 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYSPE_ join, port */
883 return; /* must exit here */
886 /* FALL THROUGH !!!! */
887 case INFO_ITYPE_VBOX:
888 /* get dialed extension's info */
889 // SCPY(exten, e_dialinginfo.id);
890 // if (strchr(exten, ','))
891 // *strchr(exten, ',') = '\0';
892 // if (!read_extension(&e_ext, exten))
893 if (!read_extension(&e_ext, e_dialinginfo.id))
895 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) extension %s not configured\n", ea_endpoint->ep_serial, e_dialinginfo.id);
896 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
897 return; /* must exit here */
900 if (e_dialinginfo.itype == INFO_ITYPE_VBOX)
902 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing directly to VBOX\n", ea_endpoint->ep_serial);
907 /* string from unconditional call forward (cfu) */
911 /* present to forwarded party */
912 if (e_ext.anon_ignore && e_callerinfo.id[0])
914 e_callerinfo.present = INFO_PRESENT_ALLOWED;
916 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
920 /* string from busy call forward (cfb) */
924 class EndpointAppPBX *checkapp = apppbx_first;
927 if (checkapp != this) /* any other endpoint except our own */
929 if (!strcmp(checkapp->e_ext.number, e_ext.number))
931 /* present to forwarded party */
932 if (e_ext.anon_ignore && e_callerinfo.id[0])
934 e_callerinfo.present = INFO_PRESENT_ALLOWED;
936 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
940 checkapp = checkapp->next;
944 /* string from no-response call forward (cfnr) */
948 /* when cfnr is done, out_setup() will setup the call */
951 /* present to forwarded party */
952 if (e_ext.anon_ignore && e_callerinfo.id[0])
954 e_callerinfo.present = INFO_PRESENT_ALLOWED;
958 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
960 e_cfnr_release = now + e_ext.cfnr_delay;
961 e_cfnr_call = now + e_ext.cfnr_delay + 1; /* call one second after release */
962 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);
966 /* call to all internal interfaces */
967 p = e_ext.interfaces;
968 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) generating multiple joins for extension %s to interfaces %s\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
972 while(*p!=',' && *p!='\0')
977 /* found interface */
978 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
979 /* hunt for mISDNport and create Port */
980 mISDNport = hunt_port(ifname, &channel);
983 trace_header("INTERFACE (not found or busy)", DIRECTION_NONE);
984 add_trace("interface", NULL, "%s", ifname);
988 /* creating INTERNAL port */
989 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
990 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
992 FATAL("No memory for DSS1 Port instance\n");
993 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
994 memset(&dialinginfo, 0, sizeof(dialinginfo));
995 SCPY(dialinginfo.id, e_dialinginfo.id);
996 dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
997 dialinginfo.ntype = e_dialinginfo.ntype;
998 /* create port_list relation */
999 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
1002 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1004 goto check_anycall_intern;
1006 /* directory.list */
1007 if (e_callerinfo.id[0] && e_ext.display_name)
1009 dirname = parse_directory(e_callerinfo.id, e_callerinfo.ntype);
1011 SCPY(e_callerinfo.name, dirname);
1013 // dss1 = (class Pdss1 *)port;
1015 //printf("INTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1016 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1017 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1018 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1019 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1020 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1021 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1022 //terminal if (e_dialinginfo.id)
1023 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1024 /* handle restricted caller ids */
1025 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);
1026 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);
1027 /* display callerid if desired for extension */
1028 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));
1029 //printf("\n\ndisplay = %s\n\n\n",message->param.setup.callerinfo.display);
1030 /* use cnip, if enabld */
1031 // if (!e_ext.centrex)
1032 // message->param.setup.callerinfo.name[0] = '\0';
1033 /* screen clip if prefix is required */
1034 if (message->param.setup.callerinfo.id[0] && e_ext.clip_prefix[0])
1036 SCPY(message->param.setup.callerinfo.id, e_ext.clip_prefix);
1037 SCAT(message->param.setup.callerinfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype, options.national, options.international));
1038 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1040 /* use internal caller id */
1041 if (e_callerinfo.extension[0] && (message->param.setup.callerinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
1043 SCPY(message->param.setup.callerinfo.id, e_callerinfo.extension);
1044 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1046 message_put(message);
1047 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1051 /* string from parallel call forward (cfp) */
1055 if (e_ext.anon_ignore && e_callerinfo.id[0])
1057 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1061 vbox_only: /* entry point for answering machine only */
1062 cfu_only: /* entry point for cfu */
1063 cfb_only: /* entry point for cfb */
1064 cfnr_only: /* entry point for cfnr */
1065 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call extension %s for external destiantion(s) '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
1070 /* only if vbox should be dialed, and terminal is given */
1071 if (!strcmp(p, "vbox") && e_ext.number[0])
1073 /* go to the end of p */
1076 /* answering vbox call */
1077 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) answering machine\n", ea_endpoint->ep_serial);
1079 if (!(port = new VBoxPort(PORT_TYPE_VBOX_OUT, &port_settings)))
1080 FATAL("No memory for VBOX Port instance\n");
1081 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocated port %s\n", ea_endpoint->ep_serial, port->p_name);
1082 UCPY(cfp, e_ext.number); /* cfp or any other direct forward/vbox */
1086 while(*p!=',' && *p!='\0')
1091 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cfp external %s\n", ea_endpoint->ep_serial, cfp);
1092 /* hunt for mISDNport and create Port */
1093 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1096 /* creating EXTERNAL port*/
1097 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1098 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, mode)))
1099 FATAL("No memory for DSS1 Port instance\n");
1100 earlyb = mISDNport->earlyb;
1104 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1105 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1111 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port found or created, which is idle.\n", ea_endpoint->ep_serial);
1112 goto check_anycall_intern;
1114 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found or created port %s\n", ea_endpoint->ep_serial, port->p_name);
1115 memset(&dialinginfo, 0, sizeof(dialinginfo));
1116 SCPY(dialinginfo.id, cfp);
1117 dialinginfo.itype = INFO_ITYPE_ISDN;
1118 dialinginfo.ntype = e_dialinginfo.ntype;
1119 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
1122 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1124 goto check_anycall_intern;
1126 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1127 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1128 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1129 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1130 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1131 /* if clip is hidden */
1132 if (e_ext.clip==CLIP_HIDE && port->p_type!=PORT_TYPE_VBOX_OUT)
1134 SCPY(message->param.setup.callerinfo.id, e_ext.callerid);
1135 SCPY(message->param.setup.callerinfo.extension, e_ext.number);
1136 message->param.setup.callerinfo.ntype = e_ext.callerid_type;
1137 message->param.setup.callerinfo.present = e_ext.callerid_present;
1139 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1140 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1141 //terminal if (e_dialinginfo.id)
1142 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1143 /* handle restricted caller ids */
1144 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);
1145 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);
1146 /* display callerid if desired for extension */
1147 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));
1148 message_put(message);
1149 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1153 check_anycall_intern:
1154 /* now we have all ports created */
1157 trace_header("INTERFACE (no extension's interface)", DIRECTION_NONE);
1159 if (!ea_endpoint->ep_join_id)
1161 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1162 return; /* must exit here */
1166 /* *********************** external call */
1168 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id);
1169 /* call to extenal interfaces */
1170 p = e_dialinginfo.id;
1174 while(*p!=',' && *p!='\0')
1175 SCCAT(number, *p++);
1179 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");
1180 /* hunt for mISDNport and create Port */
1181 /* hunt for mISDNport and create Port */
1182 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1185 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1186 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1188 goto check_anycall_extern;
1190 /* creating EXTERNAL port*/
1191 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1192 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, mode)))
1193 FATAL("No memory for DSS1 Port instance\n");
1194 earlyb = mISDNport->earlyb;
1195 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
1196 memset(&dialinginfo, 0, sizeof(dialinginfo));
1197 SCPY(dialinginfo.id, number);
1198 dialinginfo.itype = INFO_ITYPE_ISDN;
1199 dialinginfo.ntype = e_dialinginfo.ntype;
1200 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
1203 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1205 goto check_anycall_extern;
1207 // dss1 = (class Pdss1 *)port;
1208 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1209 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1210 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1211 SCPY(message->param.setup.dialinginfo.id, number);
1212 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1213 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1214 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1215 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1216 //terminal if (e_dialinginfo.id)
1217 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1218 /* handle restricted caller ids */
1219 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);
1220 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);
1221 /* display callerid if desired for extension */
1222 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));
1223 message_put(message);
1224 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1228 check_anycall_extern:
1229 /* now we have all ports created */
1232 trace_header("INTERFACE (no free ports found)", DIRECTION_NONE);
1234 if (!ea_endpoint->ep_join_id)
1236 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1237 return; /* must exit here */
1245 /* handler for endpoint
1249 int EndpointAppPBX::handler(void)
1251 if (e_crypt_state!=CM_ST_NULL)
1256 /* process answering machine (play) handling */
1259 if (e_action->index == ACTION_VBOX_PLAY)
1262 /* process action timeout */
1263 if (e_action_timeout)
1264 if (now_d >= e_action_timeout)
1266 if (e_state!=EPOINT_STATE_CONNECT)
1269 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current action timed out.\n", ea_endpoint->ep_serial);
1270 e_multipoint_cause = 0;
1271 e_multipoint_location = 0;
1272 new_state(EPOINT_STATE_IN_OVERLAP);
1275 return(1); /* we must exit, because our endpoint might be gone */
1277 e_action_timeout = 0;
1280 /* process action timeout */
1281 if (e_match_timeout)
1282 if (now_d >= e_match_timeout)
1285 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we got a match timeout.\n", ea_endpoint->ep_serial);
1287 return(1); /* we must exit, because our endpoint might be gone */
1292 /* process redialing (epoint redials to port) */
1295 if (now_d >= e_redial)
1298 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial.\n", ea_endpoint->ep_serial);
1300 new_state(EPOINT_STATE_OUT_SETUP);
1301 /* call special setup routine */
1308 /* process powerdialing (epoint redials to epoint) */
1309 if (e_powerdialing > 0)
1311 if (now_d >= e_powerdialing)
1313 e_powerdialing = -1; /* leave power dialing on */
1314 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial of powerdial.\n", ea_endpoint->ep_serial);
1317 e_ruleset = ruleset_main;
1319 e_rule = e_ruleset->rule_first;
1321 new_state(EPOINT_STATE_IN_OVERLAP);
1327 /* process call forward no response */
1330 struct port_list *portlist;
1331 struct lcr_msg *message;
1333 if (now >= e_cfnr_release)
1335 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-no-response time has expired, hanging up.\n", ea_endpoint->ep_serial);
1338 /* release all ports */
1339 while((portlist = ea_endpoint->ep_portlist))
1341 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1342 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
1343 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1344 message_put(message);
1345 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1346 ea_endpoint->free_portlist(portlist);
1349 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1350 message->param.audiopath = 0;
1351 message_put(message);
1352 /* indicate no patterns */
1353 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1354 message_put(message);
1355 /* set setup state, since we have no response from the new join */
1356 new_state(EPOINT_STATE_OUT_SETUP);
1361 if (now >= e_cfnr_call)
1363 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-busy time has expired, calling the forwarded number: %s.\n", ea_endpoint->ep_serial, e_ext.cfnr);
1369 /* handle connection to user */
1370 if (e_state == EPOINT_STATE_IDLE)
1372 /* epoint is idle, check callback */
1374 if (now_d >= e_callback)
1376 e_callback = 0; /* done with callback */
1377 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting callback.\n", ea_endpoint->ep_serial);
1378 new_state(EPOINT_STATE_OUT_SETUP);
1384 /* check for password timeout */
1386 if (e_action->index==ACTION_PASSWORD || e_action->index==ACTION_PASSWORD_WRITE)
1388 struct port_list *portlist;
1390 if (now >= e_password_timeout)
1392 e_ruleset = ruleset_main;
1394 e_rule = e_ruleset->rule_first;
1396 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) password timeout %s\n", ea_endpoint->ep_serial, e_extdialing);
1397 trace_header("PASSWORD timeout", DIRECTION_NONE);
1399 e_connectedmode = 0;
1401 new_state(EPOINT_STATE_OUT_DISCONNECT);
1402 portlist = ea_endpoint->ep_portlist;
1405 message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
1406 set_tone(portlist, "cause_10");
1416 /* doing a hookflash */
1417 void EndpointAppPBX::hookflash(void)
1421 /* be sure that we are active */
1423 e_tx_state = NOTIFY_STATE_ACTIVE;
1425 trace_header("HOOKFLASH DTMF", DIRECTION_NONE);
1427 if (ea_endpoint->ep_use > 1)
1429 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot hooflash while child process is running.\n", ea_endpoint->ep_serial);
1432 /* dialtone after pressing the hash key */
1433 process_hangup(e_join_cause, e_join_location);
1434 e_multipoint_cause = 0;
1435 e_multipoint_location = 0;
1436 port = find_port_id(ea_endpoint->ep_portlist->port_id);
1439 port->set_echotest(0);
1441 if (ea_endpoint->ep_join_id)
1443 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1445 e_ruleset = ruleset_main;
1447 e_rule = e_ruleset->rule_first;
1449 new_state(EPOINT_STATE_IN_OVERLAP);
1450 e_connectedmode = 1;
1451 SCPY(e_dialinginfo.id, e_ext.prefix);
1452 e_extdialing = e_dialinginfo.id;
1454 if (e_dialinginfo.id[0])
1456 set_tone(ea_endpoint->ep_portlist, "dialing");
1460 set_tone(ea_endpoint->ep_portlist, "dialpbx");
1467 /* messages from port
1469 /* port MESSAGE_SETUP */
1470 void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, union parameter *param)
1472 struct lcr_msg *message;
1474 int writeext; /* flags need to write extension after modification */
1476 struct interface *interface;
1478 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1480 portlist->port_type = param->setup.port_type;
1481 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
1482 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
1483 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
1484 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
1485 // e_dtmf = param->setup.dtmf;
1486 /* screen incoming caller id */
1487 interface = interface_first;
1490 if (!strcmp(e_callerinfo.interface, interface->name))
1494 interface = interface->next;
1497 do_screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface);
1499 /* process extension */
1500 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1502 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is extension\n", ea_endpoint->ep_serial);
1503 /* port makes call from extension */
1504 SCPY(e_callerinfo.extension, e_callerinfo.id);
1505 SCPY(e_ext.number, e_callerinfo.extension);
1506 SCPY(e_extension_interface, e_callerinfo.interface);
1509 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is external or voip\n", ea_endpoint->ep_serial);
1512 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1514 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1516 /* get extension's info about caller */
1517 if (!read_extension(&e_ext, e_ext.number))
1519 /* extension doesn't exist */
1520 trace_header("EXTENSION (not created)", DIRECTION_IN);
1521 add_trace("extension", NULL, "%s", e_ext.number);
1523 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
1524 new_state(EPOINT_STATE_OUT_DISCONNECT);
1525 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
1526 e_ext.number[0] = '\0'; /* no terminal */
1531 /* put prefix (next) in front of e_dialinginfo.id */
1534 SPRINT(buffer, "%s%s", e_ext.next, e_dialinginfo.id);
1535 SCPY(e_dialinginfo.id, buffer);
1536 e_ext.next[0] = '\0';
1538 } else if (e_ext.prefix[0])
1540 SPRINT(buffer, "%s%s", e_ext.prefix, e_dialinginfo.id);
1541 SCPY(e_dialinginfo.id, buffer);
1544 /* screen caller id by extension's config */
1545 e_callerinfo.screen = INFO_SCREEN_NETWORK;
1547 SCPY(e_callerinfo.name, e_ext.name);
1548 /* use caller id (or if exist: id_next_call) for this call */
1549 if (e_ext.id_next_call_present >= 0)
1551 SCPY(e_callerinfo.id, e_ext.id_next_call);
1552 /* if we restrict the pesentation */
1553 if (e_ext.id_next_call_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1554 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1555 else e_callerinfo.present = e_ext.id_next_call_present;
1556 e_callerinfo.ntype = e_ext.id_next_call_type;
1557 e_ext.id_next_call_present = -1;
1561 SCPY(e_callerinfo.id, e_ext.callerid);
1562 /* if we restrict the pesentation */
1563 if (e_ext.callerid_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1564 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1565 else e_callerinfo.present = e_ext.callerid_present;
1566 e_callerinfo.ntype = e_ext.callerid_type;
1569 /* extension is written */
1571 write_extension(&e_ext, e_ext.number);
1573 /* set volume of rx and tx */
1574 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1575 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
1577 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
1578 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
1579 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
1580 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
1581 message_put(message);
1584 /* start recording if enabled */
1585 if (e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO))
1587 /* check if we are a terminal */
1588 if (e_ext.number[0] == '\0')
1589 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
1592 port = find_port_id(portlist->port_id);
1594 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
1599 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from external port\n", ea_endpoint->ep_serial);
1600 /* no terminal identification */
1601 e_ext.number[0] = '\0';
1602 e_extension_interface[0] = '\0';
1603 memset(&e_ext, 0, sizeof(e_ext));
1604 e_ext.rights = 4; /* right to dial internat */
1608 e_ruleset = ruleset_main;
1610 e_rule = e_ruleset->rule_first;
1612 e_extdialing = e_dialinginfo.id;
1613 new_state(EPOINT_STATE_IN_SETUP);
1614 if (e_dialinginfo.id[0])
1616 set_tone(portlist, "dialing");
1619 if (e_ext.number[0])
1620 set_tone(portlist, "dialpbx");
1622 set_tone(portlist, "dialtone");
1625 if (e_state == EPOINT_STATE_IN_SETUP)
1627 /* request MORE info, if not already at higher state */
1628 new_state(EPOINT_STATE_IN_OVERLAP);
1629 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_OVERLAP);
1630 message_put(message);
1631 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1635 /* port MESSAGE_INFORMATION */
1636 void EndpointAppPBX::port_information(struct port_list *portlist, int message_type, union parameter *param)
1638 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1640 /* ignore information message without digit information */
1641 if (!param->information.id[0])
1646 /* turn off dtmf detection, in case dtmf is sent with keypad information */
1649 trace_header("DTMF (disabling due to keypad)", DIRECTION_IN);
1654 /* if vbox_play is done, the information are just used as they come */
1656 if (e_action->index == ACTION_VBOX_PLAY)
1658 /* concat dialing string */
1659 SCAT(e_dialinginfo.id, param->information.id);
1664 /* keypad when disconnect but in connected mode */
1665 if (e_state==EPOINT_STATE_OUT_DISCONNECT && e_connectedmode)
1667 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received after disconnect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1668 /* processing keypad function */
1669 if (param->information.id[0] == '0')
1676 /* keypad when connected */
1677 if (e_state == EPOINT_STATE_CONNECT)
1679 if (e_ext.keypad || e_enablekeypad)
1681 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1682 /* processing keypad function */
1683 if (param->information.id[0] == '0')
1687 if (param->information.id[0])
1688 keypad_function(param->information.id[0]);
1691 if (e_ext.number[0])
1692 trace_header("KEYPAD (not enabled by extension's settings)", DIRECTION_IN);
1694 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1699 if (e_state != EPOINT_STATE_IN_OVERLAP)
1701 if (e_ext.number[0])
1702 trace_header("KEYPAD (ignored, not connected and not dialing)", DIRECTION_IN);
1704 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1708 if (!param->information.id[0])
1710 if (e_dialinginfo.id[0]=='\0' && !e_action)
1712 set_tone(portlist, "dialing");
1715 if (e_action->index==ACTION_OUTDIAL
1716 || e_action->index==ACTION_EXTERNAL
1717 || e_action->index==ACTION_REMOTE)
1720 set_tone(portlist, "dialing");
1721 else if (!e_extdialing[0])
1722 set_tone(portlist, "dialing");
1724 /* concat dialing string */
1725 SCAT(e_dialinginfo.id, param->information.id);
1729 /* port MESSAGE_DTMF */
1730 void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
1732 /* only if dtmf detection is enabled */
1735 trace_header("DTMF (disabled)", DIRECTION_IN);
1739 trace_header("DTMF", DIRECTION_IN);
1740 add_trace("digit", NULL, "%c", param->dtmf);
1744 NOTE: vbox is now handled due to overlap state
1745 /* if vbox_play is done, the dtmf digits are just used as they come */
1747 if (e_action->index == ACTION_VBOX_PLAY)
1749 /* concat dialing string */
1750 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id))
1752 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1753 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1756 /* continue to process *X# sequences */
1760 /* check for *X# sequence */
1761 if (e_state == EPOINT_STATE_CONNECT)
1763 if (e_dtmf_time+3 < now)
1765 /* the last digit was too far in the past to be a sequence */
1766 if (param->dtmf == '*')
1767 /* only start is allowed in the sequence */
1773 /* we have a sequence of digits, see what we got */
1774 if (param->dtmf == '*')
1776 else if (param->dtmf>='0' && param->dtmf<='9')
1778 /* we need to have a star before we receive the digit of the sequence */
1779 if (e_dtmf_last == '*')
1780 e_dtmf_last = param->dtmf;
1781 } else if (param->dtmf == '#')
1784 if (e_dtmf_last>='0' && e_dtmf_last<='9')
1786 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf sequence *%c# detected.\n", ea_endpoint->ep_serial, e_dtmf_last);
1787 if (e_dtmf_last == '0')
1792 /* processing keypad function */
1794 keypad_function(e_dtmf_last);
1800 /* set last time of dtmf */
1805 /* check for ## hookflash during dialing */
1807 if (e_action->index==ACTION_PASSWORD
1808 || e_action->index==ACTION_PASSWORD_WRITE)
1810 if (param->dtmf=='#') /* current digit is '#' */
1812 if (e_state==EPOINT_STATE_IN_DISCONNECT
1813 || (e_state!=EPOINT_STATE_CONNECT && e_dtmf_time+3>=now && e_dtmf_last=='#')) /* when disconnected, just #. when dialing, ##. */
1830 /* dialing using dtmf digit */
1831 if (e_state==EPOINT_STATE_IN_OVERLAP)// && e_state==e_connectedmode)
1833 if (e_dialinginfo.id[0]=='\0' && !e_action)
1835 set_tone(portlist, "dialing");
1837 /* concat dialing string */
1838 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id))
1840 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1841 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1847 /* port MESSAGE_CRYPT */
1848 void EndpointAppPBX::port_crypt(struct port_list *portlist, int message_type, union parameter *param)
1850 /* send crypt response to cryptman */
1851 if (param->crypt.type == CR_MESSAGE_IND)
1852 cryptman_msg2man(param->crypt.data, param->crypt.len);
1854 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
1857 /* port MESSAGE_OVERLAP */
1858 void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, union parameter *param)
1860 struct lcr_msg *message;
1862 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1864 /* signal to call tool */
1865 admin_call_response(e_adminid, ADMIN_CALL_SETUP_ACK, "", 0, 0, 0);
1867 if (e_dialing_queue[0] && portlist)
1869 /* send what we have not dialed yet, because we had no setup complete */
1870 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing pending digits: '%s'\n", ea_endpoint->ep_serial, e_dialing_queue);
1871 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
1872 SCPY(message->param.information.id, e_dialing_queue);
1873 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
1874 message_put(message);
1875 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
1876 e_dialing_queue[0] = '\0';
1878 /* check if pattern is available */
1879 if (!ea_endpoint->ep_portlist->next && portlist->early_b) /* one port_list relation and tones available */
1881 /* indicate patterns */
1882 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1883 message_put(message);
1885 /* connect audio, if not already */
1886 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1887 message->param.audiopath = 1;
1888 message_put(message);
1891 /* indicate no patterns */
1892 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1893 message_put(message);
1895 /* disconnect audio, if not already */
1896 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1897 message->param.audiopath = 0;
1898 message_put(message);
1900 new_state(EPOINT_STATE_OUT_OVERLAP);
1901 /* if we are in a join */
1902 if (ea_endpoint->ep_join_id)
1904 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1905 memcpy(&message->param, param, sizeof(union parameter));
1906 message_put(message);
1910 /* port MESSAGE_PROCEEDING */
1911 void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_type, union parameter *param)
1913 struct lcr_msg *message;
1915 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1917 /* signal to call tool */
1918 admin_call_response(e_adminid, ADMIN_CALL_PROCEEDING, "", 0, 0, 0);
1920 e_state = EPOINT_STATE_OUT_PROCEEDING;
1921 /* check if pattern is availatle */
1922 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
1924 /* indicate patterns */
1925 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1926 message_put(message);
1928 /* connect audio, if not already */
1929 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1930 message->param.audiopath = 1;
1931 message_put(message);
1934 /* indicate no patterns */
1935 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1936 message_put(message);
1938 /* disconnect audio, if not already */
1939 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1940 message->param.audiopath = 0;
1941 message_put(message);
1943 /* if we are in a call */
1944 if (ea_endpoint->ep_join_id)
1946 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1947 memcpy(&message->param, param, sizeof(union parameter));
1948 message_put(message);
1952 /* port MESSAGE_ALERTING */
1953 void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type, union parameter *param)
1955 struct lcr_msg *message;
1957 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1959 /* signal to call tool */
1960 admin_call_response(e_adminid, ADMIN_CALL_ALERTING, "", 0, 0, 0);
1963 // set_tone(portlist, "hold");
1965 new_state(EPOINT_STATE_OUT_ALERTING);
1966 /* check if pattern is available */
1967 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
1969 /* indicate patterns */
1970 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1971 message_put(message);
1973 /* connect audio, if not already */
1974 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1975 message->param.audiopath = 1;
1976 message_put(message);
1979 /* indicate no patterns */
1980 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1981 message_put(message);
1983 /* disconnect audio, if not already */
1984 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1985 message->param.audiopath = 0;
1986 message_put(message);
1988 /* if we are in a call */
1989 if (ea_endpoint->ep_join_id)
1991 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1992 memcpy(&message->param, param, sizeof(union parameter));
1993 message_put(message);
1997 /* port MESSAGE_CONNECT */
1998 void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, union parameter *param)
2000 struct lcr_msg *message;
2002 unsigned int port_id = portlist->port_id;
2003 struct port_list *tportlist;
2005 struct interface *interface;
2007 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2009 /* signal to call tool */
2010 admin_call_response(e_adminid, ADMIN_CALL_CONNECT, numberrize_callerinfo(param->connectinfo.id,param->connectinfo.ntype, options.national, options.international), 0, 0, 0);
2012 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_connectinfo));
2013 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (start)\n", ea_endpoint->ep_serial);
2014 while(ea_endpoint->ep_portlist->next) /* as long as we have at least two ports */
2016 tportlist = ea_endpoint->ep_portlist;
2017 if (tportlist->port_id == port_id) /* if the first portlist is the calling one, the second must be a different one */
2018 tportlist = tportlist->next;
2019 if (tportlist->port_id == port_id)
2020 FATAL("EPOINT(%d) this should not happen since the portlist list must not have two links to the same port - exitting.\n");
2021 message = message_create(ea_endpoint->ep_serial, tportlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2022 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
2023 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2024 message_put(message);
2025 logmessage(message->type, &message->param, tportlist->port_id, DIRECTION_OUT);
2026 ea_endpoint->free_portlist(tportlist);
2028 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (end)\n", ea_endpoint->ep_serial);
2032 /* screen incoming connected id */
2033 interface = interface_first;
2036 if (!strcmp(e_connectinfo.interface, interface->name))
2040 interface = interface->next;
2043 do_screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface);
2045 /* screen connected name */
2047 SCPY(e_connectinfo.name, e_ext.name);
2049 /* add internal id to colp */
2050 SCPY(e_connectinfo.extension, e_ext.number);
2052 /* we store the connected port number */
2053 SCPY(e_extension_interface, e_connectinfo.interface);
2055 /* for internal and am calls, we get the extension's id */
2056 if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE)
2058 SCPY(e_connectinfo.id, e_ext.callerid);
2059 SCPY(e_connectinfo.extension, e_ext.number);
2060 e_connectinfo.itype = INFO_ITYPE_ISDN_EXTENSION;
2061 e_connectinfo.ntype = e_ext.callerid_type;
2062 e_connectinfo.present = e_ext.callerid_present;
2064 if (portlist->port_type==PORT_TYPE_VBOX_OUT)
2066 e_connectinfo.itype = INFO_ITYPE_VBOX;
2067 e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2070 new_state(EPOINT_STATE_CONNECT);
2072 /* set volume of rx and tx */
2073 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
2075 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2076 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2077 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
2078 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
2079 message_put(message);
2082 e_cfnr_call = e_cfnr_release = 0;
2083 if (e_ext.number[0])
2084 e_dtmf = 1; /* allow dtmf */
2087 /* other calls with no caller id (or not available for the extension) and force colp */
2088 if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE)
2090 e_connectinfo.present = INFO_PRESENT_NOTAVAIL;
2091 if (portlist->port_type==PORT_TYPE_DSS1_TE_OUT || portlist->port_type==PORT_TYPE_DSS1_NT_OUT) /* external extension answered */
2093 port = find_port_id(portlist->port_id);
2096 SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.id, &e_connectinfo.ntype, options.national, options.international));
2097 e_connectinfo.present = INFO_PRESENT_ALLOWED;
2102 /* send connect to join */
2103 if (ea_endpoint->ep_join_id)
2105 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2106 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
2107 message_put(message);
2109 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2110 message->param.audiopath = 1;
2111 message_put(message);
2112 } else if (!e_adminid)
2115 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have a callback, so we create a call with cbcaller: \"%s\".\n", ea_endpoint->ep_serial, e_cbcaller);
2116 SCPY(e_ext.number, e_cbcaller);
2117 new_state(EPOINT_STATE_IN_OVERLAP);
2118 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) callback from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2120 /* get extension's info about terminal */
2121 if (!read_extension(&e_ext, e_ext.number))
2123 /* extension doesn't exist */
2124 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2125 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
2126 new_state(EPOINT_STATE_OUT_DISCONNECT);
2127 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
2131 /* put prefix in front of e_cbdialing */
2132 SPRINT(buffer, "%s%s", e_ext.prefix, e_cbdialing);
2133 SCPY(e_dialinginfo.id, buffer);
2134 e_dialinginfo.itype = INFO_ITYPE_ISDN;
2135 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
2137 /* use caller id (or if exist: id_next_call) for this call */
2138 e_callerinfo.screen = INFO_SCREEN_NETWORK;
2139 SCPY(e_callerinfo.extension, e_ext.number);
2140 if (e_ext.id_next_call_present >= 0)
2142 SCPY(e_callerinfo.id, e_ext.id_next_call);
2143 e_callerinfo.present = e_ext.id_next_call_present;
2144 e_callerinfo.ntype = e_ext.id_next_call_type;
2145 e_ext.id_next_call_present = -1;
2146 /* extension is written */
2147 write_extension(&e_ext, e_ext.number);
2150 SCPY(e_callerinfo.id, e_ext.callerid);
2151 e_callerinfo.present = e_ext.callerid_present;
2152 e_callerinfo.ntype = e_ext.callerid_type;
2155 e_connectedmode = 1; /* dtmf-hangup & disconnect prevention */
2158 /* check if caller id is NOT authenticated */
2159 if (!parse_callbackauth(e_ext.number, &e_callbackinfo))
2161 /* make call state to enter password */
2162 new_state(EPOINT_STATE_IN_OVERLAP);
2163 e_action = &action_password_write;
2164 e_match_timeout = 0;
2165 e_match_to_action = NULL;
2166 e_dialinginfo.id[0] = '\0';
2167 e_extdialing = strchr(e_dialinginfo.id, '\0');
2168 e_password_timeout = now+20;
2172 /* incoming call (callback) */
2173 e_ruleset = ruleset_main;
2175 e_rule = e_ruleset->rule_first;
2177 e_extdialing = e_dialinginfo.id;
2178 if (e_dialinginfo.id[0])
2180 set_tone(portlist, "dialing");
2184 set_tone(portlist, "dialpbx");
2187 } else /* testcall */
2189 set_tone(portlist, "hold");
2192 /* start recording if enabled, not when answering machine answers */
2193 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))
2195 /* check if we are a terminal */
2196 if (e_ext.number[0] == '\0')
2197 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
2200 port = find_port_id(portlist->port_id);
2202 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
2207 /* port MESSAGE_DISCONNECT MESSAGE_RELEASE */
2208 void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
2210 struct lcr_msg *message;
2212 unsigned int port_id = portlist->port_id;
2216 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2218 /* signal to call tool */
2219 admin_call_response(e_adminid, (message_type==MESSAGE_DISCONNECT)?ADMIN_CALL_DISCONNECT:ADMIN_CALL_RELEASE, "", param->disconnectinfo.cause, param->disconnectinfo.location, 0);
2221 //#warning does this work? only disconnect when incoming port hat not already disconnected yet?
2222 if (e_state==EPOINT_STATE_IN_DISCONNECT && message_type!=MESSAGE_RELEASE)// || e_state==EPOINT_STATE_OUT_DISCONNECT || e_state==EPOINT_STATE_IDLE)
2224 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are already disconnected.\n", ea_endpoint->ep_serial);
2229 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);
2230 collect_cause(&e_multipoint_cause, &e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location);
2231 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new multipoint cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location);
2233 /* check if we have more than one portlist relation and we just ignore the disconnect */
2234 if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist->next)
2236 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the disconnect was from a multipoint call. we just release that relation.\n", ea_endpoint->ep_serial);
2237 portlist = ea_endpoint->ep_portlist;
2240 if (portlist->port_id == port_id)
2242 portlist = portlist->next;
2245 FATAL("EPOINT(%d) no portlist related to the calling port.\n", ea_endpoint->ep_serial);
2246 if (message_type != MESSAGE_RELEASE)
2248 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2249 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2250 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2251 message_put(message);
2252 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2254 ea_endpoint->free_portlist(portlist);
2255 return; /* one relation removed */
2257 if (e_state == EPOINT_STATE_CONNECT)
2259 /* use cause from port after connect */
2260 cause = param->disconnectinfo.cause;
2261 location = param->disconnectinfo.location;
2264 /* use multipoint cause if no connect yet */
2265 if (e_multipoint_cause)
2267 cause = e_multipoint_cause;
2268 location = e_multipoint_location;
2271 cause = CAUSE_NOUSER;
2272 location = LOCATION_PRIVATE_LOCAL;
2276 e_cfnr_call = e_cfnr_release = 0;
2278 /* process hangup */
2279 process_hangup(e_join_cause, e_join_location);
2280 e_multipoint_cause = 0;
2281 e_multipoint_location = 0;
2283 if (message_type == MESSAGE_DISCONNECT)
2285 /* tone to disconnected end */
2286 SPRINT(buffer, "cause_%02x", cause);
2287 if (ea_endpoint->ep_portlist)
2288 set_tone(ea_endpoint->ep_portlist, buffer);
2290 new_state(EPOINT_STATE_IN_DISCONNECT);
2293 if (ea_endpoint->ep_join_id)
2295 int haspatterns = 0;
2296 /* check if pattern is available */
2297 if (ea_endpoint->ep_portlist)
2298 if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->early_b)
2299 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
2300 && message_type != MESSAGE_RELEASE) // if we release, we are done
2304 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has patterns.\n", ea_endpoint->ep_serial);
2305 /* indicate patterns */
2306 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2307 message_put(message);
2308 /* connect audio, if not already */
2309 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2310 message->param.audiopath = 1;
2311 message_put(message);
2312 /* send disconnect */
2313 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2314 memcpy(&message->param, param, sizeof(union parameter));
2315 message_put(message);
2316 /* disable encryption if disconnected */
2317 //PERROR("REMOVE ME: state =%d, %d\n", e_crypt_state, e_crypt);
2319 cryptman_message(CI_DISCONNECT_IND, NULL, 0);
2323 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
2326 if (message_type == MESSAGE_RELEASE)
2327 ea_endpoint->free_portlist(portlist);
2328 release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, callcause, portcause */
2329 return; /* must exit here */
2332 /* port MESSAGE_TIMEOUT */
2333 void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type, union parameter *param)
2337 trace_header("TIMEOUT", DIRECTION_IN);
2338 message_type = MESSAGE_DISCONNECT;
2339 switch (param->state)
2341 case PORT_STATE_OUT_SETUP:
2342 case PORT_STATE_OUT_OVERLAP:
2343 add_trace("state", NULL, "outgoing setup/dialing");
2345 /* no user responding */
2346 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2347 return; /* must exit here */
2349 case PORT_STATE_IN_SETUP:
2350 case PORT_STATE_IN_OVERLAP:
2351 add_trace("state", NULL, "incoming setup/dialing");
2352 param->disconnectinfo.cause = CAUSE_INVALID; /* number incomplete */
2353 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2356 case PORT_STATE_OUT_PROCEEDING:
2357 add_trace("state", NULL, "outgoing proceeding");
2359 param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
2360 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2361 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2362 return; /* must exit here */
2364 case PORT_STATE_IN_PROCEEDING:
2365 add_trace("state", NULL, "incoming proceeding");
2366 param->disconnectinfo.cause = CAUSE_NOUSER;
2367 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL; /* no user responding */
2370 case PORT_STATE_OUT_ALERTING:
2371 add_trace("state", NULL, "outgoing alerting");
2373 param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
2374 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2375 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2376 return; /* must exit here */
2378 case PORT_STATE_CONNECT:
2379 add_trace("state", NULL, "connect");
2381 param->disconnectinfo.cause = CAUSE_NORMAL; /* normal */
2382 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2383 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2384 return; /* must exit here */
2386 case PORT_STATE_IN_ALERTING:
2387 add_trace("state", NULL, "incoming alerting");
2388 param->disconnectinfo.cause = CAUSE_NOANSWER;
2389 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2392 case PORT_STATE_IN_DISCONNECT:
2393 case PORT_STATE_OUT_DISCONNECT:
2394 add_trace("state", NULL, "disconnect");
2396 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
2397 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2398 return; /* must exit here */
2401 param->disconnectinfo.cause = 31; /* normal unspecified */
2402 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2405 /* release call, disconnect isdn */
2407 new_state(EPOINT_STATE_OUT_DISCONNECT);
2408 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2409 SCPY(e_tone, cause);
2412 set_tone(portlist, cause);
2413 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2414 portlist = portlist->next;
2416 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
2419 /* port MESSAGE_NOTIFY */
2420 void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, union parameter *param)
2422 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2424 struct lcr_msg *message;
2425 const char *logtext = "";
2428 /* signal to call tool */
2429 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);
2430 if (param->notifyinfo.notify)
2432 e_rx_state = track_notify(e_rx_state, param->notifyinfo.notify);
2435 /* if we get notification from stack, local shows if we disabled/enabled audio stream */
2436 if (param->notifyinfo.local) switch(param->notifyinfo.notify)
2438 case INFO_NOTIFY_REMOTE_HOLD:
2439 case INFO_NOTIFY_USER_SUSPENDED:
2440 /* tell call about it */
2441 if (ea_endpoint->ep_join_id)
2443 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2444 message->param.audiopath = 0;
2445 message_put(message);
2449 case INFO_NOTIFY_REMOTE_RETRIEVAL:
2450 case INFO_NOTIFY_USER_RESUMED:
2451 /* set volume of rx and tx */
2452 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
2453 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
2456 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2457 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2458 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
2459 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
2460 message_put(message);
2462 /* set current tone */
2464 set_tone(portlist, e_tone);
2465 /* tell call about it */
2466 if (ea_endpoint->ep_join_id)
2468 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2469 message->param.audiopath = 1;
2470 message_put(message);
2475 /* get name of notify */
2476 switch(param->notifyinfo.notify)
2482 logtext = "USER_SUSPENDED";
2485 logtext = "BEARER_SERVICE_CHANGED";
2488 logtext = "USER_RESUMED";
2491 logtext = "CONFERENCE_ESTABLISHED";
2494 logtext = "CONFERENCE_DISCONNECTED";
2497 logtext = "OTHER_PARTY_ADDED";
2500 logtext = "ISOLATED";
2503 logtext = "REATTACHED";
2506 logtext = "OTHER_PARTY_ISOLATED";
2509 logtext = "OTHER_PARTY_REATTACHED";
2512 logtext = "OTHER_PARTY_SPLIT";
2515 logtext = "OTHER_PARTY_DISCONNECTED";
2518 logtext = "CONFERENCE_FLOATING";
2521 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
2524 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
2527 logtext = "CALL_IS_A_WAITING_CALL";
2530 logtext = "DIVERSION_ACTIVATED";
2533 logtext = "RESERVED_CT_1";
2536 logtext = "RESERVED_CT_2";
2539 logtext = "REVERSE_CHARGING";
2542 logtext = "REMOTE_HOLD";
2545 logtext = "REMOTE_RETRIEVAL";
2548 logtext = "CALL_IS_DIVERTING";
2551 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
2556 /* notify call if available */
2557 if (ea_endpoint->ep_join_id)
2559 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOTIFY);
2560 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
2561 message_put(message);
2566 /* port MESSAGE_FACILITY */
2567 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
2569 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2571 struct lcr_msg *message;
2573 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_FACILITY);
2574 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2575 message_put(message);
2578 /* port MESSAGE_SUSPEND */
2579 /* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
2580 void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
2582 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2584 /* epoint is now parked */
2585 ea_endpoint->ep_park = 1;
2586 memcpy(ea_endpoint->ep_park_callid, param->parkinfo.callid, sizeof(ea_endpoint->ep_park_callid));
2587 ea_endpoint->ep_park_len = (param->parkinfo.len>8)?8:param->parkinfo.len;
2589 /* remove port relation */
2590 ea_endpoint->free_portlist(portlist);
2593 /* port MESSAGE_RESUME */
2594 /* NOTE: before resume, the active-notification must be done in order to set call mixer */
2595 void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
2597 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2599 /* epoint is now resumed */
2600 ea_endpoint->ep_park = 0;
2605 /* port sends message to the endpoint
2607 void EndpointAppPBX::ea_message_port(unsigned int port_id, int message_type, union parameter *param)
2609 struct port_list *portlist;
2610 struct lcr_msg *message;
2612 portlist = ea_endpoint->ep_portlist;
2615 if (port_id == portlist->port_id)
2617 portlist = portlist->next;
2621 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);
2625 // PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
2626 switch(message_type)
2628 case MESSAGE_DATA: /* data from port */
2629 /* check if there is a call */
2630 if (!ea_endpoint->ep_join_id)
2632 /* continue if only one portlist */
2633 if (ea_endpoint->ep_portlist->next != NULL)
2635 /* forward message */
2636 message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2639 case MESSAGE_TONE_EOF: /* tone is end of file */
2640 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
2643 if (e_action->index == ACTION_VBOX_PLAY)
2647 if (e_action->index == ACTION_EFI)
2654 case MESSAGE_TONE_COUNTER: /* counter info received */
2655 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);
2657 if (e_action->index == ACTION_VBOX_PLAY)
2659 e_vbox_counter = param->counter.current;
2660 if (param->counter.max >= 0)
2661 e_vbox_counter_max = param->counter.max;
2665 /* PORT sends SETUP message */
2667 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);
2668 if (e_state!=EPOINT_STATE_IDLE)
2670 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
2673 port_setup(portlist, message_type, param);
2676 /* PORT sends INFORMATION message */
2677 case MESSAGE_INFORMATION: /* additional digits received */
2678 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);
2679 port_information(portlist, message_type, param);
2682 /* PORT sends FACILITY message */
2683 case MESSAGE_FACILITY:
2684 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2685 port_facility(portlist, message_type, param);
2688 /* PORT sends DTMF message */
2689 case MESSAGE_DTMF: /* dtmf digits received */
2690 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);
2691 port_dtmf(portlist, message_type, param);
2694 /* PORT sends CRYPT message */
2695 case MESSAGE_CRYPT: /* crypt response received */
2696 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) crypt response=%d\n", ea_endpoint->ep_serial, param->crypt.type);
2697 port_crypt(portlist, message_type, param);
2700 /* PORT sends MORE message */
2701 case MESSAGE_OVERLAP:
2702 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);
2703 if (e_state != EPOINT_STATE_OUT_SETUP)
2705 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);
2708 port_overlap(portlist, message_type, param);
2711 /* PORT sends PROCEEDING message */
2712 case MESSAGE_PROCEEDING: /* port is proceeding */
2713 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);
2714 if (e_state!=EPOINT_STATE_OUT_SETUP
2715 && e_state!=EPOINT_STATE_OUT_OVERLAP)
2717 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);
2720 port_proceeding(portlist, message_type, param);
2723 /* PORT sends ALERTING message */
2724 case MESSAGE_ALERTING:
2725 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);
2726 if (e_state!=EPOINT_STATE_OUT_SETUP
2727 && e_state!=EPOINT_STATE_OUT_OVERLAP
2728 && e_state!=EPOINT_STATE_OUT_PROCEEDING)
2730 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);
2733 port_alerting(portlist, message_type, param);
2736 /* PORT sends CONNECT message */
2737 case MESSAGE_CONNECT:
2738 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);
2739 if (e_state!=EPOINT_STATE_OUT_SETUP
2740 && e_state!=EPOINT_STATE_OUT_OVERLAP
2741 && e_state!=EPOINT_STATE_OUT_PROCEEDING
2742 && e_state!=EPOINT_STATE_OUT_ALERTING)
2744 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
2747 port_connect(portlist, message_type, param);
2750 /* PORT sends DISCONNECT message */
2751 case MESSAGE_DISCONNECT: /* port is disconnected */
2752 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);
2753 port_disconnect_release(portlist, message_type, param);
2756 /* PORT sends a RELEASE message */
2757 case MESSAGE_RELEASE: /* port releases */
2758 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);
2759 /* portlist is release at port_disconnect_release, thanx Paul */
2760 port_disconnect_release(portlist, message_type, param);
2763 /* PORT sends a TIMEOUT message */
2764 case MESSAGE_TIMEOUT:
2765 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);
2766 port_timeout(portlist, message_type, param);
2767 break; /* release */
2769 /* PORT sends a NOTIFY message */
2770 case MESSAGE_NOTIFY:
2771 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);
2772 port_notify(portlist, message_type, param);
2775 /* PORT sends a SUSPEND message */
2776 case MESSAGE_SUSPEND:
2777 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);
2778 port_suspend(portlist, message_type, param);
2779 break; /* suspend */
2781 /* PORT sends a RESUME message */
2782 case MESSAGE_RESUME:
2783 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);
2784 port_resume(portlist, message_type, param);
2788 kann nach dem test gelöscht werden, da eine direkte funktion im join und im mISDN zum austausch der message existiert
2789 /* port assigns bchannel */
2790 case MESSAGE_BCHANNEL: /* bchannel assignment messafe */
2791 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);
2792 /* only one port is expected to be connected to bchannel */
2793 message = message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2794 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_IN);
2800 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);
2803 /* Note: this endpoint may be destroyed, so we MUST return */
2807 /* messages from join
2809 /* join MESSAGE_CRYPT */
2810 void EndpointAppPBX::join_crypt(struct port_list *portlist, int message_type, union parameter *param)
2812 switch(param->crypt.type)
2814 /* message from remote port to "crypt manager" */
2815 case CU_ACTK_REQ: /* activate key-exchange */
2816 case CU_ACTS_REQ: /* activate shared key */
2817 case CU_DACT_REQ: /* deactivate */
2818 case CU_INFO_REQ: /* request last info message */
2819 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2822 /* message from "crypt manager" to user */
2823 case CU_ACTK_CONF: /* key-echange done */
2824 case CU_ACTS_CONF: /* shared key done */
2825 case CU_DACT_CONF: /* deactivated */
2826 case CU_DACT_IND: /* deactivated */
2827 case CU_ERROR_IND: /* receive error message */
2828 case CU_INFO_IND: /* receive info message */
2829 case CU_INFO_CONF: /* receive info message */
2830 encrypt_result(param->crypt.type, (char *)param->crypt.data);
2834 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);
2838 /* join MESSAGE_INFORMATION */
2839 void EndpointAppPBX::join_information(struct port_list *portlist, int message_type, union parameter *param)
2841 struct lcr_msg *message;
2847 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2848 memcpy(&message->param.information, ¶m->information, sizeof(struct dialing_info));
2849 message_put(message);
2850 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2851 portlist = portlist->next;
2855 /* join MESSAGE_FACILITY */
2856 void EndpointAppPBX::join_facility(struct port_list *portlist, int message_type, union parameter *param)
2858 struct lcr_msg *message;
2860 if (!e_ext.facility && e_ext.number[0])
2867 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_FACILITY);
2868 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2869 message_put(message);
2870 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2871 portlist = portlist->next;
2875 /* join MESSAGE_MORE */
2876 void EndpointAppPBX::join_overlap(struct port_list *portlist, int message_type, union parameter *param)
2878 struct lcr_msg *message;
2880 new_state(EPOINT_STATE_IN_OVERLAP);
2883 if (e_join_pattern && e_ext.own_setup)
2885 /* disconnect audio */
2886 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2887 message->param.audiopath = 0;
2888 message_put(message);
2890 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
2892 if (e_dialinginfo.id[0])
2893 set_tone(portlist, "dialing");
2895 set_tone(portlist, "dialtone");
2898 if (e_dialinginfo.id[0])
2900 set_tone(portlist, "dialing");
2903 if (e_ext.number[0])
2904 set_tone(portlist, "dialpbx");
2906 set_tone(portlist, "dialtone");
2910 /* join MESSAGE_PROCEEDING */
2911 void EndpointAppPBX::join_proceeding(struct port_list *portlist, int message_type, union parameter *param)
2913 struct lcr_msg *message;
2915 new_state(EPOINT_STATE_IN_PROCEEDING);
2917 /* own proceeding tone */
2920 /* connect / disconnect audio */
2921 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2922 if (e_ext.own_proceeding)
2923 message->param.audiopath = 0;
2925 message->param.audiopath = 1;
2926 message_put(message);
2928 // UCPY(e_join_tone, "proceeding");
2931 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
2932 message_put(message);
2933 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2935 set_tone(portlist, "proceeding");
2938 /* join MESSAGE_ALERTING */
2939 void EndpointAppPBX::join_alerting(struct port_list *portlist, int message_type, union parameter *param)
2941 struct lcr_msg *message;
2943 new_state(EPOINT_STATE_IN_ALERTING);
2945 /* own alerting tone */
2948 /* connect / disconnect audio */
2949 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2950 if (e_ext.own_alerting)
2951 message->param.audiopath = 0;
2953 message->param.audiopath = 1;
2954 message_put(message);
2958 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
2959 message_put(message);
2960 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2962 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
2964 set_tone(portlist, "ringing");
2967 if (e_ext.number[0])
2968 set_tone(portlist, "ringpbx");
2970 set_tone(portlist, "ringing");
2973 /* join MESSAGE_CONNECT */
2974 void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type, union parameter *param)
2976 struct lcr_msg *message;
2978 new_state(EPOINT_STATE_CONNECT);
2979 // UCPY(e_join_tone, "");
2981 if (e_ext.number[0])
2982 e_dtmf = 1; /* allow dtmf */
2985 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_callerinfo));
2988 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
2989 memcpy(&message->param, param, sizeof(union parameter));
2991 /* screen clip if prefix is required */
2992 if (e_ext.number[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0])
2994 SCPY(message->param.connectinfo.id, e_ext.clip_prefix);
2995 SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype, options.national, options.international));
2996 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2999 /* use internal caller id */
3000 if (e_ext.number[0] && e_connectinfo.extension[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
3002 SCPY(message->param.connectinfo.id, e_connectinfo.extension);
3003 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
3006 /* handle restricted caller ids */
3007 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);
3008 /* display callerid if desired for extension */
3009 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));
3011 /* use conp, if enabld */
3012 // if (!e_ext.centrex)
3013 // message->param.connectinfo.name[0] = '\0';
3016 message_put(message);
3017 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3019 set_tone(portlist, NULL);
3021 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3022 message->param.audiopath = 1;
3023 message_put(message);
3027 /* join MESSAGE_DISCONNECT MESSAGE_RELEASE */
3028 void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *param)
3031 struct lcr_msg *message;
3032 struct port_list *portlist = NULL;
3035 /* be sure that we are active */
3037 e_tx_state = NOTIFY_STATE_ACTIVE;
3039 /* we are powerdialing, if e_powerdialing is set and limit is not exceeded if given */
3040 if (e_powerdialing && ((e_powercount+1)<e_powerlimit || e_powerlimit<1))
3042 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
3044 /* set time for power dialing */
3045 e_powerdialing = now_d + e_powerdelay; /* set redial in the future */
3048 /* set redial tone */
3049 if (ea_endpoint->ep_portlist)
3053 set_tone(ea_endpoint->ep_portlist, "redial");
3054 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);
3055 /* send proceeding when powerdialing and still setup (avoid dialing timeout) */
3056 if (e_state==EPOINT_STATE_IN_OVERLAP)
3058 new_state(EPOINT_STATE_IN_PROCEEDING);
3059 if (ea_endpoint->ep_portlist)
3061 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3062 message_put(message);
3063 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3065 /* caused the error, that the first knock sound was not there */
3066 /* set_tone(portlist, "proceeding"); */
3068 /* send display of powerdialing */
3069 if (e_ext.display_dialing)
3071 portlist = ea_endpoint->ep_portlist;
3074 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3076 SPRINT(message->param.notifyinfo.display, "Retry %d of %d", e_powercount, e_powerlimit);
3078 SPRINT(message->param.notifyinfo.display, "Retry %d", e_powercount);
3079 message_put(message);
3080 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3081 portlist = portlist->next;
3090 if ((e_state!=EPOINT_STATE_CONNECT
3091 && e_state!=EPOINT_STATE_OUT_DISCONNECT
3092 && e_state!=EPOINT_STATE_IN_OVERLAP
3093 && e_state!=EPOINT_STATE_IN_PROCEEDING
3094 && e_state!=EPOINT_STATE_IN_ALERTING)
3095 || !ea_endpoint->ep_portlist) /* or no port */
3097 process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
3098 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause); /* RELEASE_TYPE, join, port */
3099 return; /* must exit here */
3104 e_join_cause = param->disconnectinfo.cause;
3105 e_join_location = param->disconnectinfo.location;
3108 /* on release we need the audio again! */
3109 if (message_type == MESSAGE_RELEASE)
3112 ea_endpoint->ep_join_id = 0;
3114 /* disconnect and select tone */
3115 new_state(EPOINT_STATE_OUT_DISCONNECT);
3116 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
3117 /* if own_cause, we must release the join */
3118 if (e_ext.own_cause /* own cause */
3119 || !e_join_pattern) /* no patterns */
3121 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);
3122 if (message_type != MESSAGE_RELEASE)
3123 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
3125 } else /* else we enable audio */
3127 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3128 message->param.audiopath = 1;
3129 message_put(message);
3131 /* send disconnect message */
3132 SCPY(e_tone, cause);
3133 portlist = ea_endpoint->ep_portlist;
3136 set_tone(portlist, cause);
3137 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
3138 portlist = portlist->next;
3142 /* join MESSAGE_SETUP */
3143 void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, union parameter *param)
3145 struct lcr_msg *message;
3146 // struct interface *interface;
3148 /* if we already in setup state, we just update the dialing with new digits */
3149 if (e_state == EPOINT_STATE_OUT_SETUP
3150 || e_state == EPOINT_STATE_OUT_OVERLAP)
3152 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we are in setup state, so we do overlap dialing.\n", ea_endpoint->ep_serial);
3153 /* if digits changed, what we have already dialed */
3154 if (!!strncmp(e_dialinginfo.id,param->setup.dialinginfo.id,strlen(e_dialinginfo.id)))
3156 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);
3157 /* release all ports */
3158 while((portlist = ea_endpoint->ep_portlist))
3160 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
3161 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
3162 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3163 message_put(message);
3164 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3165 ea_endpoint->free_portlist(portlist);
3168 /* disconnect audio */
3169 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3170 message->param.audiopath = 0;
3171 message_put(message);
3173 /* get dialing info */
3174 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3175 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3176 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3177 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3178 new_state(EPOINT_STATE_OUT_OVERLAP);
3181 e_redial = now_d + 1; /* set redial one second in the future */
3184 /* if we have a pending redial, so we just adjust the dialing number */
3187 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);
3188 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3191 if (!ea_endpoint->ep_portlist)
3193 PERROR("ERROR: overlap dialing to a NULL port relation\n");
3195 if (ea_endpoint->ep_portlist->next)
3197 PERROR("ERROR: overlap dialing to a port_list port relation\n");
3199 if (e_state == EPOINT_STATE_OUT_SETUP)
3202 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);
3203 SCAT(e_dialing_queue, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3207 /* get what we have not dialed yet */
3208 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));
3209 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
3210 SCPY(message->param.information.id, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3211 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
3212 message_put(message);
3213 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3215 /* always store what we have dialed or queued */
3216 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3220 if (e_state != EPOINT_STATE_IDLE)
3222 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
3225 /* if an internal extension is dialed, copy that number */
3226 if (param->setup.dialinginfo.itype==INFO_ITYPE_ISDN_EXTENSION || param->setup.dialinginfo.itype==INFO_ITYPE_VBOX)
3227 SCPY(e_ext.number, param->setup.dialinginfo.id);
3228 /* if an internal extension is dialed, get extension's info about caller */
3229 if (e_ext.number[0])
3231 if (!read_extension(&e_ext, e_ext.number))
3233 e_ext.number[0] = '\0';
3234 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the called terminal='%s' is not found in directory tree!\n", ea_endpoint->ep_serial, e_ext.number);
3238 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3239 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3240 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3241 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3243 /* process (voice over) data calls */
3244 if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO)
3246 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) handling data call as audio call: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
3247 memset(&e_capainfo, 0, sizeof(e_capainfo));
3248 e_capainfo.bearer_capa = INFO_BC_AUDIO;
3249 e_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
3250 e_capainfo.bearer_info1 = (options.law=='u')?INFO_INFO1_ULAW:INFO_INFO1_ALAW;
3253 new_state(EPOINT_STATE_OUT_SETUP);
3254 /* call special setup routine */
3258 /* join MESSAGE_mISDNSIGNAL */
3259 void EndpointAppPBX::join_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param)
3261 struct lcr_msg *message;
3265 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
3266 memcpy(&message->param, param, sizeof(union parameter));
3267 message_put(message);
3268 portlist = portlist->next;
3272 /* join MESSAGE_NOTIFY */
3273 void EndpointAppPBX::join_notify(struct port_list *portlist, int message_type, union parameter *param)
3275 struct lcr_msg *message;
3278 if (param->notifyinfo.notify)
3280 new_state = track_notify(e_tx_state, param->notifyinfo.notify);
3281 // /* if notification was generated locally, we turn hold music on/off */
3282 // if (param->notifyinfo.local)
3283 // 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)
3288 if (new_state!=NOTIFY_STATE_HOLD && new_state!=NOTIFY_STATE_SUSPEND)
3290 if (!strcmp(e_tone, "hold")) // don't interrupt other tones
3294 set_tone(portlist, "");
3295 portlist = portlist->next;
3298 portlist = ea_endpoint->ep_portlist;
3303 if (new_state==NOTIFY_STATE_HOLD || new_state==NOTIFY_STATE_SUSPEND)
3307 set_tone(portlist, "hold");
3308 portlist = portlist->next;
3310 portlist = ea_endpoint->ep_portlist;
3315 /* save new state */
3316 e_tx_state = new_state;
3319 /* notify port(s) about it */
3322 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3323 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
3324 /* handle restricted caller ids */
3325 apply_callerid_restriction(&e_ext, message->param.notifyinfo.id, &message->param.notifyinfo.ntype, &message->param.notifyinfo.present, 0, message->param.notifyinfo.extension, NULL);
3326 /* display callerid if desired for extension */
3327 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));
3328 message_put(message);
3329 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3330 portlist = portlist->next;
3334 /* JOIN sends messages to the endpoint
3336 void EndpointAppPBX::ea_message_join(unsigned int join_id, int message_type, union parameter *param)
3338 struct port_list *portlist;
3339 struct lcr_msg *message;
3343 PERROR("EPOINT(%d) error: JOIN == NULL.\n", ea_endpoint->ep_serial);
3347 portlist = ea_endpoint->ep_portlist;
3349 /* send MESSAGE_DATA to port */
3350 if (message_type == MESSAGE_DATA)
3352 if (join_id == ea_endpoint->ep_join_id) // still linked with JOIN
3354 /* skip if no port relation */
3357 /* skip if more than one port relation */
3360 /* forward audio data to port */
3361 message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3366 // 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);
3367 switch(message_type)
3369 /* JOIN SENDS TONE message */
3371 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);
3372 set_tone(portlist, param->tone.name);
3375 /* JOIN SENDS CRYPT message */
3377 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);
3378 join_crypt(portlist, message_type, param);
3381 /* JOIN sends INFORMATION message */
3382 case MESSAGE_INFORMATION:
3383 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);
3384 join_information(portlist, message_type, param);
3387 /* JOIN sends FACILITY message */
3388 case MESSAGE_FACILITY:
3389 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);
3390 join_facility(portlist, message_type, param);
3393 /* JOIN sends OVERLAP message */
3394 case MESSAGE_OVERLAP:
3395 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received 'more info required'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3396 if (e_state!=EPOINT_STATE_IN_SETUP
3397 && e_state!=EPOINT_STATE_IN_OVERLAP)
3399 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3402 join_overlap(portlist, message_type, param);
3405 /* JOIN sends PROCEEDING message */
3406 case MESSAGE_PROCEEDING:
3407 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);
3408 if(e_state!=EPOINT_STATE_IN_OVERLAP)
3410 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3413 join_proceeding(portlist, message_type, param);
3416 /* JOIN sends ALERTING message */
3417 case MESSAGE_ALERTING:
3418 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);
3419 if (e_state!=EPOINT_STATE_IN_OVERLAP
3420 && e_state!=EPOINT_STATE_IN_PROCEEDING)
3422 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state.\n", ea_endpoint->ep_serial);
3425 join_alerting(portlist, message_type, param);
3428 /* JOIN sends CONNECT message */
3429 case MESSAGE_CONNECT:
3430 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);
3431 if (e_state!=EPOINT_STATE_IN_OVERLAP
3432 && e_state!=EPOINT_STATE_IN_PROCEEDING
3433 && e_state!=EPOINT_STATE_IN_ALERTING)
3435 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
3438 join_connect(portlist, message_type, param);
3441 /* JOIN sends DISCONNECT/RELEASE message */
3442 case MESSAGE_DISCONNECT: /* JOIN disconnect */
3443 case MESSAGE_RELEASE: /* JOIN releases */
3444 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);
3445 join_disconnect_release(message_type, param);
3448 /* JOIN sends SETUP message */
3450 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);
3451 join_setup(portlist, message_type, param);
3454 /* JOIN sends special mISDNSIGNAL message */
3455 case MESSAGE_mISDNSIGNAL: /* isdn message to port */
3456 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);
3457 join_mISDNsignal(portlist, message_type, param);
3461 kann nach dem test gelöscht werden, da eine direkte funktion im join und im mISDN zum austausch der message existiert
3462 /* JOIN requests bchannel */
3463 case MESSAGE_BCHANNEL: /* indicates the need of own bchannel access */
3464 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);
3465 /* only one port is expected to be connected to bchannel */
3472 set_tone(portlist, NULL);
3473 message = message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3474 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3478 /* JOIN has pattern available */
3479 case MESSAGE_PATTERN: /* indicating pattern available */
3480 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);
3481 if (!e_join_pattern)
3483 PDEBUG(DEBUG_EPOINT, "-> pattern becomes available\n");
3488 set_tone(portlist, NULL);
3489 portlist = portlist->next;
3491 /* connect our audio tx and rx (blueboxing should be possibe before connect :)*/
3492 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3493 message->param.audiopath = 1;
3494 message_put(message);
3498 /* JOIN has no pattern available */
3499 case MESSAGE_NOPATTERN: /* indicating no pattern available */
3500 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);
3503 PDEBUG(DEBUG_EPOINT, "-> pattern becomes unavailable\n");
3505 /* disconnect our audio tx and rx */
3506 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3507 message->param.audiopath = 0;
3508 message_put(message);
3513 /* JOIN (dunno at the moment) */
3514 case MESSAGE_REMOTE_AUDIO:
3515 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);
3516 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3517 message->param.audiopath = param->channel;
3518 message_put(message);
3522 /* JOIN sends a notify message */
3523 case MESSAGE_NOTIFY:
3524 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);
3525 join_notify(portlist, message_type, param);
3528 /* JOIN wants keypad / dtml */
3529 case MESSAGE_ENABLEKEYPAD:
3530 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);
3533 trace_header("ENABLE KEYPAD", DIRECTION_NONE);
3538 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);
3543 /* pick_join will connect the first incoming call found. the endpoint
3544 * will receivce a MESSAGE_CONNECT.
3546 int match_list(char *list, char *item)
3548 char *end, *next = NULL;
3550 /* no list make matching */
3556 /* eliminate white spaces */
3557 while (*list <= ' ')
3564 /* if end of list is reached, we return */
3565 if (list[0] == '\0')
3567 /* if we have more than one entry (left) */
3568 if ((end = strchr(list, ',')))
3571 next = end = strchr(list, '\0');
3572 while (*(end-1) <= ' ')
3574 /* if string part matches item */
3575 if (!strncmp(list, item, end-list))
3581 void EndpointAppPBX::pick_join(char *extensions)
3583 struct lcr_msg *message;
3584 struct port_list *portlist;
3586 class EndpointAppPBX *eapp, *found;
3588 class JoinPBX *joinpbx;
3589 struct join_relation *relation;
3592 /* find an endpoint that is ringing internally or vbox with higher priority */
3595 eapp = apppbx_first;
3598 if (eapp!=this && ea_endpoint->ep_portlist)
3600 portlist = eapp->ea_endpoint->ep_portlist;
3603 if ((port = find_port_id(portlist->port_id)))
3605 if (port->p_type == PORT_TYPE_VBOX_OUT)
3607 if (match_list(extensions, eapp->e_ext.number))
3614 if ((port->p_type==PORT_TYPE_DSS1_NT_OUT || port->p_type==PORT_TYPE_DSS1_TE_OUT)
3615 && port->p_state==PORT_STATE_OUT_ALERTING)
3616 if (match_list(extensions, eapp->e_ext.number))
3621 portlist = portlist->next;
3629 /* if no endpoint found */
3632 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);
3634 set_tone(ea_endpoint->ep_portlist, "cause_10");
3635 message_disconnect_port(ea_endpoint->ep_portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
3636 new_state(EPOINT_STATE_OUT_DISCONNECT);
3641 if (ea_endpoint->ep_join_id)
3643 PERROR("EPOINT(%d) we already have a join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3646 if (!eapp->ea_endpoint->ep_join_id)
3648 PERROR("EPOINT(%d) ringing endpoint has no join.\n", ea_endpoint->ep_serial);
3651 join = find_join_id(eapp->ea_endpoint->ep_join_id);
3654 PERROR("EPOINT(%d) ringing endpoint's join not found.\n", ea_endpoint->ep_serial);
3657 if (join->j_type != JOIN_TYPE_PBX)
3659 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ringing endpoint's join is not a PBX join, so we must reject.\n", ea_endpoint->ep_serial);
3662 joinpbx = (class JoinPBX *)join;
3663 relation = joinpbx->j_relation;
3666 PERROR("EPOINT(%d) ringing endpoint's join has no relation. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3669 while (relation->epoint_id != eapp->ea_endpoint->ep_serial)
3671 relation = relation->next;
3674 PERROR("EPOINT(%d) ringing endpoint's join has no relation to that join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3679 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found ringing endpoint: %d.\n", ea_endpoint->ep_serial, eapp->ea_endpoint->ep_serial);
3681 if (options.deb & DEBUG_EPOINT)
3683 class Join *debug_c = join_first;
3684 class Endpoint *debug_e = epoint_first;
3685 class Port *debug_p = port_first;
3687 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(before)");
3689 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3692 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3693 debug_c = debug_c->next;
3695 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3698 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3699 debug_e = debug_e->next;
3701 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3704 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld (active)\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3705 debug_p = debug_p->next;
3710 ea_endpoint->ep_join_id = eapp->ea_endpoint->ep_join_id; /* we get the join */
3711 relation->epoint_id = ea_endpoint->ep_serial; /* the join gets us */
3712 eapp->ea_endpoint->ep_join_id = 0; /* the ringing endpoint will get disconnected */
3714 /* connnecting our endpoint */
3715 new_state(EPOINT_STATE_CONNECT);
3716 if (e_ext.number[0])
3718 set_tone(ea_endpoint->ep_portlist, NULL);
3720 /* now we send a release to the ringing endpoint */
3721 message = message_create(ea_endpoint->ep_join_id, eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3722 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
3723 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3724 message_put(message);
3726 /* we send a connect to the join with our caller id */
3727 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CONNECT);
3728 SCPY(message->param.connectinfo.id, e_callerinfo.id);
3729 message->param.connectinfo.present = e_callerinfo.present;
3730 message->param.connectinfo.screen = e_callerinfo.screen;
3731 message->param.connectinfo.itype = e_callerinfo.itype;
3732 message->param.connectinfo.ntype = e_callerinfo.ntype;
3733 message_put(message);
3735 /* we send a connect to our port with the remote callerid */
3736 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3737 SCPY(message->param.connectinfo.id, eapp->e_callerinfo.id);
3738 message->param.connectinfo.present = eapp->e_callerinfo.present;
3739 message->param.connectinfo.screen = eapp->e_callerinfo.screen;
3740 message->param.connectinfo.itype = eapp->e_callerinfo.itype;
3741 message->param.connectinfo.ntype = eapp->e_callerinfo.ntype;
3742 /* handle restricted caller ids */
3743 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);
3744 /* display callerid if desired for extension */
3745 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));
3746 message_put(message);
3748 /* we send a connect to the audio path (not for vbox) */
3749 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3750 message->param.audiopath = 1;
3751 message_put(message);
3753 /* beeing paranoid, we make call update */
3754 joinpbx->j_updatebridge = 1;
3756 if (options.deb & DEBUG_EPOINT)
3758 class Join *debug_c = join_first;
3759 class Endpoint *debug_e = epoint_first;
3760 class Port *debug_p = port_first;
3762 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(after)");
3764 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3767 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3768 debug_c = debug_c->next;
3770 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3773 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3774 debug_e = debug_e->next;
3776 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3779 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3780 debug_p = debug_p->next;
3786 /* join calls (look for a join that is on hold (same isdn interface/terminal))
3788 void EndpointAppPBX::join_join(void)
3790 struct lcr_msg *message;
3791 struct join_relation *our_relation, *other_relation;
3792 struct join_relation **our_relation_pointer, **other_relation_pointer;
3793 class Join *our_join, *other_join;
3794 class JoinPBX *our_joinpbx, *other_joinpbx;
3795 class EndpointAppPBX *other_eapp; class Endpoint *temp_epoint;
3796 class Port *our_port, *other_port;
3797 class Pdss1 *our_pdss1, *other_pdss1;
3799 /* are we a candidate to join a join */
3800 our_join = find_join_id(ea_endpoint->ep_join_id);
3803 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3806 if (our_join->j_type != JOIN_TYPE_PBX)
3808 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: join is not a pbx join.\n", ea_endpoint->ep_serial);
3811 our_joinpbx = (class JoinPBX *)our_join;
3812 if (!ea_endpoint->ep_portlist)
3814 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
3817 if (!e_ext.number[0])
3819 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
3822 our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
3825 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
3828 if ((our_port->p_type&PORT_CLASS_mISDN_MASK) != PORT_CLASS_mISDN_DSS1)
3830 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not isdn.\n", ea_endpoint->ep_serial);
3833 our_pdss1 = (class Pdss1 *)our_port;
3835 /* find an endpoint that is on hold and has the same mISDNport that we are on */
3836 other_eapp = apppbx_first;
3839 if (other_eapp == this)
3841 other_eapp = other_eapp->next;
3844 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);
3845 if (other_eapp->e_ext.number[0] /* has terminal */
3846 && other_eapp->ea_endpoint->ep_portlist /* has port */
3847 && other_eapp->ea_endpoint->ep_join_id) /* has join */
3849 other_port = find_port_id(other_eapp->ea_endpoint->ep_portlist->port_id);
3850 if (other_port) /* port still exists */
3852 if (other_port->p_type==PORT_TYPE_DSS1_NT_OUT
3853 || other_port->p_type==PORT_TYPE_DSS1_NT_IN) /* port is isdn nt-mode */
3855 other_pdss1 = (class Pdss1 *)other_port;
3856 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);
3857 if (other_pdss1->p_m_hold /* port is on hold */
3858 && other_pdss1->p_m_mISDNport == our_pdss1->p_m_mISDNport /* same isdn interface */
3859 && other_pdss1->p_m_d_ces == our_pdss1->p_m_d_ces) /* same tei+sapi */
3863 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of other type!\n", ea_endpoint->ep_serial);
3867 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port doesn't exist enymore.\n", ea_endpoint->ep_serial);
3870 other_eapp = other_eapp->next;
3874 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn interface with port on hold.\n", ea_endpoint->ep_serial);
3877 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port on hold found.\n", ea_endpoint->ep_serial);
3879 /* if we have the same join */
3880 if (other_eapp->ea_endpoint->ep_join_id == ea_endpoint->ep_join_id)
3882 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we an the other have the same join.\n", ea_endpoint->ep_serial);
3885 other_join = find_join_id(other_eapp->ea_endpoint->ep_join_id);
3888 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3891 if (other_join->j_type != JOIN_TYPE_PBX)
3893 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join is not a pbx join.\n", ea_endpoint->ep_serial);
3896 other_joinpbx = (class JoinPBX *)other_join;
3897 if (our_joinpbx->j_partyline && other_joinpbx->j_partyline)
3899 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both joins are partylines.\n", ea_endpoint->ep_serial);
3903 /* remove relation to endpoint for join on hold */
3904 other_relation = other_joinpbx->j_relation;
3905 other_relation_pointer = &other_joinpbx->j_relation;
3906 while(other_relation)
3908 if (other_relation->epoint_id == other_eapp->ea_endpoint->ep_serial)
3910 /* detach other endpoint on hold */
3911 *other_relation_pointer = other_relation->next;
3912 FREE(other_relation, sizeof(struct join_relation));
3914 other_relation = *other_relation_pointer;
3915 other_eapp->ea_endpoint->ep_join_id = 0;
3919 /* change join/hold pointer of endpoint to the new join */
3920 temp_epoint = find_epoint_id(other_relation->epoint_id);
3923 if (temp_epoint->ep_join_id == other_join->j_serial)
3924 temp_epoint->ep_join_id = our_join->j_serial;
3927 other_relation_pointer = &other_relation->next;
3928 other_relation = other_relation->next;
3930 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint on hold removed, other enpoints on join relinked (to our join).\n", ea_endpoint->ep_serial);
3932 /* join call relations */
3933 our_relation = our_joinpbx->j_relation;
3934 our_relation_pointer = &our_joinpbx->j_relation;
3937 our_relation_pointer = &our_relation->next;
3938 our_relation = our_relation->next;
3940 *our_relation_pointer = other_joinpbx->j_relation;
3941 other_joinpbx->j_relation = NULL;
3942 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) relations joined.\n", ea_endpoint->ep_serial);
3944 /* release endpoint on hold */
3945 message = message_create(other_joinpbx->j_serial, other_eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3946 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */
3947 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3948 message_put(message);
3950 /* if we are not a partyline, we get partyline state from other join */
3951 our_joinpbx->j_partyline += other_joinpbx->j_partyline;
3953 /* remove empty join */
3955 PDEBUG(DEBUG_EPOINT, "EPOINT(%d)d-join completely removed!\n");
3957 /* mixer must update */
3958 our_joinpbx->j_updatebridge = 1; /* update mixer flag */
3960 /* we send a retrieve to that endpoint */
3961 // mixer will update the hold-state of the join and send it to the endpoints is changes
3965 /* check if we have an external call
3966 * this is used to check for encryption ability
3968 int EndpointAppPBX::check_external(const char **errstr, class Port **port)
3970 struct join_relation *relation;
3972 class JoinPBX *joinpbx;
3973 class Endpoint *epoint;
3975 /* some paranoia check */
3976 if (!ea_endpoint->ep_portlist)
3978 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we have no port.\n", ea_endpoint->ep_serial);
3979 *errstr = "No Call";
3982 if (!e_ext.number[0])
3984 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we are not internal extension.\n", ea_endpoint->ep_serial);
3985 *errstr = "No Call";
3989 /* check if we have a join with 2 parties */
3990 join = find_join_id(ea_endpoint->ep_join_id);
3993 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have currently no join.\n", ea_endpoint->ep_serial);
3994 *errstr = "No Call";
3997 if (join->j_type != JOIN_TYPE_PBX)
3999 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join is not a pbx join.\n", ea_endpoint->ep_serial);
4000 *errstr = "No PBX Call";
4003 joinpbx = (class JoinPBX *)join;
4004 relation = joinpbx->j_relation;
4007 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no relation.\n", ea_endpoint->ep_serial);
4008 *errstr = "No Call";
4011 if (!relation->next)
4013 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd relation.\n", ea_endpoint->ep_serial);
4014 *errstr = "No Call";
4017 if (relation->next->next)
4019 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has more than two relations.\n", ea_endpoint->ep_serial);
4020 *errstr = "Err: Conference";
4023 if (relation->epoint_id == ea_endpoint->ep_serial)
4025 relation = relation->next;
4026 if (relation->epoint_id == ea_endpoint->ep_serial)
4028 PERROR("EPOINT(%d) SOFTWARE ERROR: both join relations are related to our endpoint.\n", ea_endpoint->ep_serial);
4029 *errstr = "Software Error";
4034 /* check remote port for external call */
4035 epoint = find_epoint_id(relation->epoint_id);
4038 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd endpoint.\n", ea_endpoint->ep_serial);
4039 *errstr = "No Call";
4042 if (!epoint->ep_portlist)
4044 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not port.\n", ea_endpoint->ep_serial);
4045 *errstr = "No Call";
4048 *port = find_port_id(epoint->ep_portlist->port_id);
4051 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has an none existing port.\n", ea_endpoint->ep_serial);
4052 *errstr = "No Call";
4055 if (((*port)->p_type&PORT_CLASS_mISDN_MASK)!=PORT_CLASS_mISDN_DSS1) /* port is not external isdn */
4057 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not an external port.\n", ea_endpoint->ep_serial);
4058 *errstr = "No Ext Call";
4061 if ((*port)->p_state != PORT_STATE_CONNECT)
4063 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint's port is not in connected state.\n", ea_endpoint->ep_serial);
4064 *errstr = "No Ext Connect";
4070 void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsigned int port_id, int dir)
4072 const char *logtext = "unknown";
4075 switch(message_type)
4078 trace_header("SETUP", dir);
4079 if (dir == DIRECTION_OUT)
4080 add_trace("to", NULL, "CH(%lu)", port_id);
4081 if (dir == DIRECTION_IN)
4082 add_trace("from", NULL, "CH(%lu)", port_id);
4083 if (param->setup.callerinfo.extension[0])
4084 add_trace("extension", NULL, "%s", param->setup.callerinfo.extension);
4085 add_trace("caller id", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype, options.national, options.international));
4086 switch(param->setup.callerinfo.present)
4088 case INFO_PRESENT_RESTRICTED:
4089 add_trace("caller id", "present", "restricted");
4091 case INFO_PRESENT_ALLOWED:
4092 add_trace("caller id", "present", "allowed");
4095 add_trace("caller id", "present", "not available");
4097 if (param->setup.redirinfo.id[0])
4099 add_trace("redir'ing", "number", "%s", numberrize_callerinfo(param->setup.redirinfo.id, param->setup.redirinfo.ntype, options.national, options.international));
4100 switch(param->setup.redirinfo.present)
4102 case INFO_PRESENT_RESTRICTED:
4103 add_trace("redir'ing", "present", "restricted");
4105 case INFO_PRESENT_ALLOWED:
4106 add_trace("redir'ing", "present", "allowed");
4109 add_trace("redir'ing", "present", "not available");
4112 if (param->setup.dialinginfo.id[0])
4113 add_trace("dialing", NULL, "%s", param->setup.dialinginfo.id);
4114 if (param->setup.dialinginfo.display[0])
4115 add_trace("display", NULL, "%s", param->setup.dialinginfo.display);
4116 if (param->setup.dialinginfo.sending_complete)
4117 add_trace("complete", NULL, "true", param->setup.dialinginfo.sending_complete);
4121 case MESSAGE_OVERLAP:
4122 trace_header("SETUP ACKNOWLEDGE", dir);
4123 if (dir == DIRECTION_OUT)
4124 add_trace("to", NULL, "CH(%lu)", port_id);
4125 if (dir == DIRECTION_IN)
4126 add_trace("from", NULL, "CH(%lu)", port_id);
4130 case MESSAGE_PROCEEDING:
4131 trace_header("PROCEEDING", dir);
4132 if (dir == DIRECTION_OUT)
4133 add_trace("to", NULL, "CH(%lu)", port_id);
4134 if (dir == DIRECTION_IN)
4135 add_trace("from", NULL, "CH(%lu)", port_id);
4139 case MESSAGE_ALERTING:
4140 trace_header("ALERTING", dir);
4141 if (dir == DIRECTION_OUT)
4142 add_trace("to", NULL, "CH(%lu)", port_id);
4143 if (dir == DIRECTION_IN)
4144 add_trace("from", NULL, "CH(%lu)", port_id);
4148 case MESSAGE_CONNECT:
4149 trace_header("CONNECT", dir);
4150 if (dir == DIRECTION_OUT)
4151 add_trace("to", NULL, "CH(%lu)", port_id);
4152 if (dir == DIRECTION_IN)
4153 add_trace("from", NULL, "CH(%lu)", port_id);
4154 if (param->connectinfo.extension[0])
4155 add_trace("extension", NULL, "%s", param->connectinfo.extension);
4156 add_trace("connect id", "number", "%s", numberrize_callerinfo(param->connectinfo.id, param->connectinfo.ntype, options.national, options.international));
4157 switch(param->connectinfo.present)
4159 case INFO_PRESENT_RESTRICTED:
4160 add_trace("connect id", "present", "restricted");
4162 case INFO_PRESENT_ALLOWED:
4163 add_trace("connect id", "present", "allowed");
4166 add_trace("connect id", "present", "not available");
4168 if (param->connectinfo.display[0])
4169 add_trace("display", NULL, "%s", param->connectinfo.display);
4173 case MESSAGE_DISCONNECT:
4174 case MESSAGE_RELEASE:
4175 if (message_type == MESSAGE_DISCONNECT)
4176 trace_header("DISCONNECT", dir);
4178 trace_header("RELEASE", dir);
4179 if (dir == DIRECTION_OUT)
4180 add_trace("to", NULL, "CH(%lu)", port_id);
4181 if (dir == DIRECTION_IN)
4182 add_trace("from", NULL, "CH(%lu)", port_id);
4183 add_trace("cause", "value", "%d", param->disconnectinfo.cause);
4184 switch(param->disconnectinfo.location)
4187 add_trace("cause", "location", "0-User");
4189 case LOCATION_PRIVATE_LOCAL:
4190 add_trace("cause", "location", "1-Local-PBX");
4192 case LOCATION_PUBLIC_LOCAL:
4193 add_trace("cause", "location", "2-Local-Exchange");
4195 case LOCATION_TRANSIT:
4196 add_trace("cause", "location", "3-Transit");
4198 case LOCATION_PUBLIC_REMOTE:
4199 add_trace("cause", "location", "4-Remote-Exchange");
4201 case LOCATION_PRIVATE_REMOTE:
4202 add_trace("cause", "location", "5-Remote-PBX");
4204 case LOCATION_INTERNATIONAL:
4205 add_trace("cause", "location", "7-International-Exchange");
4207 case LOCATION_BEYOND:
4208 add_trace("cause", "location", "10-Beyond-Interworking");
4211 add_trace("cause", "location", "%d", param->disconnectinfo.location);
4213 if (param->disconnectinfo.display[0])
4214 add_trace("display", NULL, "%s", param->disconnectinfo.display);
4218 case MESSAGE_NOTIFY:
4219 switch(param->notifyinfo.notify)
4225 logtext = "USER_SUSPENDED";
4228 logtext = "BEARER_SERVICE_CHANGED";
4231 logtext = "USER_RESUMED";
4234 logtext = "CONFERENCE_ESTABLISHED";
4237 logtext = "CONFERENCE_DISCONNECTED";
4240 logtext = "OTHER_PARTY_ADDED";
4243 logtext = "ISOLATED";
4246 logtext = "REATTACHED";
4249 logtext = "OTHER_PARTY_ISOLATED";
4252 logtext = "OTHER_PARTY_REATTACHED";
4255 logtext = "OTHER_PARTY_SPLIT";
4258 logtext = "OTHER_PARTY_DISCONNECTED";
4261 logtext = "CONFERENCE_FLOATING";
4264 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
4267 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
4270 logtext = "CALL_IS_A_WAITING_CALL";
4273 logtext = "DIVERSION_ACTIVATED";
4276 logtext = "RESERVED_CT_1";
4279 logtext = "RESERVED_CT_2";
4282 logtext = "REVERSE_CHARGING";
4285 logtext = "REMOTE_HOLD";
4288 logtext = "REMOTE_RETRIEVAL";
4291 logtext = "CALL_IS_DIVERTING";
4294 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
4298 trace_header("NOTIFY", dir);
4299 if (dir == DIRECTION_OUT)
4300 add_trace("to", NULL, "CH(%lu)", port_id);
4301 if (dir == DIRECTION_IN)
4302 add_trace("from", NULL, "CH(%lu)", port_id);
4303 if (param->notifyinfo.notify)
4304 add_trace("indicator", NULL, "%s", logtext);
4305 if (param->notifyinfo.id[0])
4307 add_trace("redir'on", "number", "%s", numberrize_callerinfo(param->notifyinfo.id, param->notifyinfo.ntype, options.national, options.international));
4308 switch(param->notifyinfo.present)
4310 case INFO_PRESENT_RESTRICTED:
4311 add_trace("redir'on", "present", "restricted");
4313 case INFO_PRESENT_ALLOWED:
4314 add_trace("redir'on", "present", "allowed");
4317 add_trace("redir'on", "present", "not available");
4320 if (param->notifyinfo.display[0])
4321 add_trace("display", NULL, "%s", param->notifyinfo.display);
4325 case MESSAGE_INFORMATION:
4326 trace_header("INFORMATION", dir);
4327 if (dir == DIRECTION_OUT)
4328 add_trace("to", NULL, "CH(%lu)", port_id);
4329 if (dir == DIRECTION_IN)
4330 add_trace("from", NULL, "CH(%lu)", port_id);
4331 if (param->information.id[0])
4332 add_trace("dialing", NULL, "%s", param->information.id);
4333 if (param->information.display[0])
4334 add_trace("display", NULL, "%s", param->information.display);
4335 if (param->information.sending_complete)
4336 add_trace("complete", NULL, "true", param->information.sending_complete);
4340 case MESSAGE_FACILITY:
4341 trace_header("FACILITY", 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);
4350 trace_header("TONE", dir);
4351 if (dir == DIRECTION_OUT)
4352 add_trace("to", NULL, "CH(%lu)", port_id);
4353 if (dir == DIRECTION_IN)
4354 add_trace("from", NULL, "CH(%lu)", port_id);
4355 if (param->tone.name[0])
4357 add_trace("directory", NULL, "%s", param->tone.dir[0]?param->tone.dir:"default");
4358 add_trace("name", NULL, "%s", param->tone.name);
4360 add_trace("off", NULL, NULL);
4364 case MESSAGE_SUSPEND:
4365 case MESSAGE_RESUME:
4366 if (message_type == MESSAGE_SUSPEND)
4367 trace_header("SUSPEND", dir);
4369 trace_header("RESUME", dir);
4370 if (dir == DIRECTION_OUT)
4371 add_trace("to", NULL, "CH(%lu)", port_id);
4372 if (dir == DIRECTION_IN)
4373 add_trace("from", NULL, "CH(%lu)", port_id);
4374 if (param->parkinfo.len)
4375 add_trace("length", NULL, "%d", param->parkinfo.len);
4380 case MESSAGE_BCHANNEL:
4381 trace_header("BCHANNEL", dir);
4382 switch(param->bchannel.type)
4384 case BCHANNEL_REQUEST:
4385 add_trace("type", NULL, "request");
4387 case BCHANNEL_ASSIGN:
4388 add_trace("type", NULL, "assign");
4390 case BCHANNEL_ASSIGN_ACK:
4391 add_trace("type", NULL, "assign_ack");
4393 case BCHANNEL_REMOVE:
4394 add_trace("type", NULL, "remove");
4396 case BCHANNEL_REMOVE_ACK:
4397 add_trace("type", NULL, "remove_ack");
4400 if (param->bchannel.addr)
4401 add_trace("address", NULL, "%x", param->bchannel.addr);
4407 PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message_type);
4411 void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cause, int location, const char *display)
4413 struct lcr_msg *message;
4417 if (!portlist->port_id)
4420 if (!e_connectedmode)
4422 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT);
4423 message->param.disconnectinfo.cause = cause;
4424 message->param.disconnectinfo.location = location;
4426 SCPY(message->param.disconnectinfo.display, display);
4428 SCPY(message->param.disconnectinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4431 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
4433 SCPY(message->param.notifyinfo.display, display);
4435 SCPY(message->param.notifyinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4437 message_put(message);
4438 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);