1 /*****************************************************************************\
3 ** Linux Call Router **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
8 ** The EndpointAppPBX implements PBX4Linux **
10 \*****************************************************************************/
15 class EndpointAppPBX *apppbx_first = NULL;
18 * EndpointAppPBX constructor
20 EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint, int origin) : EndpointApp(epoint, origin)
22 class EndpointAppPBX **apppointer;
24 /* add application to chain */
26 apppointer = &apppbx_first;
28 apppointer = &((*apppointer)->next);
32 memset(&e_ext, 0, sizeof(struct extension));
33 // *************** NOTE: also change value in read_extension() **************
34 e_ext.rights = 4; /* international */
35 e_ext.rx_gain = e_ext.tx_gain = 0;
36 e_state = EPOINT_STATE_IDLE;
37 e_ext.number[0] = '\0';
38 e_extension_interface[0] = '\0';
39 memset(&e_callerinfo, 0, sizeof(struct caller_info));
40 memset(&e_dialinginfo, 0, sizeof(struct dialing_info));
41 memset(&e_connectinfo, 0, sizeof(struct connect_info));
42 memset(&e_redirinfo, 0, sizeof(struct redir_info));
43 memset(&e_capainfo, 0, sizeof(struct capa_info));
46 e_ruleset = ruleset_main;
48 e_rule = e_ruleset->rule_first;
53 e_match_to_action = NULL;
55 e_extdialing = e_dialinginfo.id;
59 // e_join_tone[0] = e_hold_tone[0] = '\0';
60 e_join_pattern /*= e_hold_pattern*/ = 0;
63 e_adminid = 0; // will be set, if call was initiated via admin socket
68 e_cbdialing[0] = '\0';
71 memset(&e_callbackinfo, 0, sizeof(struct caller_info));
79 e_password_timeout = 0;
80 e_multipoint_cause = 0;
81 e_multipoint_location = 0;
82 e_dialing_queue[0] = '\0';
84 e_crypt_state = CM_ST_NULL;
85 e_crypt_keyengine_busy = 0;
86 e_crypt_info[0] = '\0';
89 e_tx_state = NOTIFY_STATE_ACTIVE;
90 e_rx_state = NOTIFY_STATE_ACTIVE;
91 e_join_cause = e_join_location = 0;
92 /*********************************
93 *********************************
94 ********* ATTENTION *************
95 *********************************
96 *********************************/
97 /* if you add new values, that must be initialized, also check if they must
98 * be initialized when doing callback
104 * EpointAppPBX destructor
106 EndpointAppPBX::~EndpointAppPBX(void)
108 class EndpointAppPBX *temp, **tempp;
112 tempp = &apppbx_first;
122 FATAL("Endpoint not in endpoint's list.\n");
129 * trace header for application
131 void EndpointAppPBX::trace_header(char *name, int direction)
135 char msgtext[sizeof(_trace.name)];
139 /* init trace with given values */
142 numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype, options.national, options.international),
146 ea_endpoint->ep_serial,
153 /* set new endpoint state
155 void EndpointAppPBX::new_state(int state)
158 if (e_state != state)
160 trace_header("NEW STATE", DIRECTION_NONE);
161 add_trace("state", "old", "%s", state_name[e_state]);
162 add_trace("state", "new", "%s", state_name[state]);
170 /* release join and port (as specified)
172 void EndpointAppPBX::release(int release, int joinlocation, int joincause, int portlocation, int portcause)
174 struct port_list *portlist;
175 struct lcr_msg *message;
178 /* message to test call */
179 admin_call_response(e_adminid, ADMIN_CALL_RELEASE, "", joincause, joinlocation, 0);
181 /* if a release is pending */
182 if (release==RELEASE_JOIN || release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY)
184 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): do pending release (joincause %d location %d)\n", ea_endpoint->ep_serial, joincause, joinlocation);
185 if (ea_endpoint->ep_join_id)
187 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_RELEASE);
188 message->param.disconnectinfo.cause = joincause;
189 message->param.disconnectinfo.location = joinlocation;
190 message_put(message);
191 ea_endpoint->ep_join_id = 0;
195 if (release != RELEASE_PORT_JOINONLY)
198 join_release(e_hold_id, ea_endpoint->ep_serial, 1, joinlocation, joincause);
203 if (release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY)
205 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release (portcause %d portlocation)\n", ea_endpoint->ep_serial, portcause, portlocation);
206 while((portlist = ea_endpoint->ep_portlist))
208 if (portlist->port_id)
210 SPRINT(cause, "cause_%02x", portcause);
211 set_tone(portlist, cause);
212 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
213 message->param.disconnectinfo.cause = portcause;
214 message->param.disconnectinfo.location = portlocation;
215 message_put(message);
216 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
218 ea_endpoint->free_portlist(portlist);
221 /* if callback is enabled, call back with the given caller id */
224 /* reset some stuff */
225 new_state(EPOINT_STATE_IDLE);
226 memset(&e_connectinfo, 0, sizeof(struct connect_info));
227 memset(&e_redirinfo, 0, sizeof(struct redir_info));
228 e_start = e_stop = 0;
229 e_ruleset = ruleset_main;
231 e_rule = e_ruleset->rule_first;
233 e_action_timeout = 0;
235 e_match_to_action = NULL;
237 e_extdialing = e_dialinginfo.id;
245 e_multipoint_cause = 0;
246 e_multipoint_location = 0;
247 e_dialing_queue[0] = '\0';
249 e_crypt_state = CM_ST_NULL;
250 e_crypt_keyengine_busy = 0;
251 e_crypt_info[0] = '\0';
255 e_tx_state = NOTIFY_STATE_ACTIVE;
256 e_rx_state = NOTIFY_STATE_ACTIVE;
257 e_join_cause = e_join_location = 0;
259 /* the caller info of the callback user */
260 memcpy(&e_callbackinfo, &e_callerinfo, sizeof(e_callbackinfo));
261 memset(&e_dialinginfo, 0, sizeof(e_dialinginfo));
262 /* create dialing by callerinfo */
263 if (e_ext.number[0] && e_extension_interface[0])
265 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to internal: %s interface %s\n", ea_endpoint->ep_serial, e_ext.number, e_extension_interface);
266 /* create callback to the current terminal */
267 SCPY(e_dialinginfo.id, e_ext.number);
268 SCPY(e_dialinginfo.interfaces, e_extension_interface);
269 e_dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
270 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
275 SCPY(e_dialinginfo.id, e_cbto);
278 /* numberrize caller id and use it to dial to the callback */
279 SCPY(e_dialinginfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype, options.national, options.international));
281 e_dialinginfo.itype = INFO_ITYPE_ISDN;
282 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
283 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to external: %s\n", ea_endpoint->ep_serial, e_dialinginfo.id);
288 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release of epoint itself.\n", ea_endpoint->ep_serial);
289 ea_endpoint->ep_use--; /* when e_lock is 0, the endpoint will be deleted */
295 /* cancel callerid if restricted, unless anon-ignore is enabled at extension or port is of type external (so called police gets caller id :)*/
296 void apply_callerid_restriction(struct extension *ext, char *id, int *ntype, int *present, int *screen, char *extension, char *name)
298 PDEBUG(DEBUG_EPOINT, "id='%s' ntype=%d present=%d screen=%d extension='%s' name='%s'\n", (id)?id:"NULL", (ntype)?*ntype:-1, (present)?*present:-1, (screen)?*screen:-1, (extension)?extension:"NULL", (name)?name:"NULL");
300 /* caller id is not restricted, so we do nothing */
301 if (*present != INFO_PRESENT_RESTRICTED)
304 /* only extensions are restricted */
308 /* if we enabled anonymouse ignore */
309 if (ext->anon_ignore)
312 /* else we remove the caller id */
316 *ntype = INFO_NTYPE_UNKNOWN;
318 // *screen = INFO_SCREEN_USER;
319 // maybe we should not make voip address anonymous
322 // maybe it's no fraud to present extension id
324 // extension[0] = '\0';
329 /* used display message to display callerid as available */
330 char *EndpointAppPBX::apply_callerid_display(char *id, int itype, int ntype, int present, int screen, char *extension, char *name)
332 static char display[81];
335 char *cid = numberrize_callerinfo(id, ntype, options.national, options.international);
337 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) id='%s' itype=%d ntype=%d present=%d screen=%d extension='%s' name='%s'\n", ea_endpoint->ep_serial, (id)?id:"NULL", itype, ntype, present, screen, (extension)?extension:"NULL", (name)?name:"NULL");
346 /* NOTE: is caller is is not available for this extesion, it has been removed by apply_callerid_restriction already */
348 /* internal extension's caller id */
349 if (extension[0] && e_ext.display_int)
352 SCAT(display, extension);
355 if (itype == INFO_ITYPE_VBOX)
356 SCAT(display, "(vbox)");
358 SCAT(display, "(int)");
361 /* external caller id */
362 if (!extension[0] && e_ext.display_ext)
368 if (present == INFO_PRESENT_RESTRICTED)
369 SCAT(display, "anonymous");
371 SCAT(display, "unknown");
378 /* display if callerid is anonymouse but available due anon-ignore */
379 if (e_ext.display_anon && present==INFO_PRESENT_RESTRICTED)
382 SCAT(display, "unknown");
385 SCAT(display, " anon");
388 /* display if callerid is anonymouse but available due anon-ignore */
389 if (e_ext.display_fake && screen==INFO_SCREEN_USER && present!=INFO_PRESENT_NULL)
395 if (present == INFO_PRESENT_RESTRICTED)
396 SCAT(display, "anonymous");
398 SCAT(display, "unknown");
403 SCAT(display, " fake");
407 if (name[0] && e_ext.display_name)
409 if (!display[0] && cid[0])
420 * uses the current state to notify activity
422 void EndpointAppPBX::notify_active(void)
424 struct port_list *portlist = ea_endpoint->ep_portlist;
425 struct lcr_msg *message;
430 case NOTIFY_STATE_ACTIVE:
431 /* we are already active, so we don't do anything */
434 case NOTIFY_STATE_SUSPEND:
435 notify = INFO_NOTIFY_USER_RESUMED;
438 set_tone(portlist, NULL);
439 portlist = portlist->next;
441 portlist = ea_endpoint->ep_portlist;
444 case NOTIFY_STATE_HOLD:
445 notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
448 set_tone(portlist, NULL);
449 portlist = portlist->next;
451 portlist = ea_endpoint->ep_portlist;
454 case NOTIFY_STATE_CONFERENCE:
455 notify = INFO_NOTIFY_CONFERENCE_DISCONNECTED;
458 set_tone(portlist, NULL);
459 portlist = portlist->next;
461 portlist = ea_endpoint->ep_portlist;
465 PERROR("unknown e_tx_state = %d\n", e_tx_state);
471 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
472 message->param.notifyinfo.notify = notify;
473 message_put(message);
474 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
475 portlist = portlist->next;
481 * keypad functions during call. one example to use this is to put a call on hold or start a conference
483 void EndpointAppPBX::keypad_function(char digit)
486 /* we must be in a call, in order to send messages to the call */
487 if (e_ext.number[0] == '\0')
489 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) IGNORING keypad received not from extension.\n", ea_endpoint->ep_serial);
495 /* join conference */
497 if (ea_endpoint->ep_join_id == 0)
499 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad received during connect but not during a call.\n", ea_endpoint->ep_serial);
502 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join call with call on hold\n", ea_endpoint->ep_serial);
508 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) shared key encryption selected.\n", ea_endpoint->ep_serial);
512 /* crypt key-exchange */
514 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) key exchange encryption selected.\n", ea_endpoint->ep_serial);
520 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) encryption off selected.\n", ea_endpoint->ep_serial);
525 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) unsupported keypad digit '%c'.\n", ea_endpoint->ep_serial, digit);
530 /* set tone pattern for port */
531 void EndpointAppPBX::set_tone(struct port_list *portlist, char *tone)
533 struct lcr_msg *message;
538 /* store for suspended processes */
542 if (e_join_pattern /* pattern are provided */
543 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_SETUP)
544 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_OVERLAP)
545 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_IN_PROCEEDING)
546 && !(e_ext.own_alerting && e_state == EPOINT_STATE_IN_ALERTING)
547 && !(e_ext.own_cause && e_state == EPOINT_STATE_IN_DISCONNECT)
548 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_SETUP)
549 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_OVERLAP)
550 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_OUT_PROCEEDING)
551 && !(e_ext.own_alerting && e_state == EPOINT_STATE_OUT_ALERTING)
552 && !(e_ext.own_cause && e_state == EPOINT_STATE_OUT_DISCONNECT)
553 && tone[0] && !!strncmp(tone,"crypt_*",6))
555 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) tone not provided since patterns are available\n", ea_endpoint->ep_serial);
561 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_TONE);
562 SCPY(message->param.tone.dir, e_ext.tones_dir[0]?e_ext.tones_dir:options.tones_dir);
563 SCPY(message->param.tone.name, tone);
564 message_put(message);
565 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
568 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port to notify tone.\n", ea_endpoint->ep_serial);
575 * hunts an mISDNport that is available for an outgoing call
576 * if no ifname was given, any interface that is not an extension
579 struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel)
581 struct interface *interface;
582 struct interface_port *ifport, *ifport_start;
583 struct select_channel *selchannel;
584 struct mISDNport *mISDNport;
587 interface = interface_first;
589 /* first find the given interface or, if not given, one with no extension */
594 /* check for given interface */
597 if (!strcasecmp(interface->name, ifname))
599 /* found explicit interface */
600 trace_header("CHANNEL SELECTION (found interface)", DIRECTION_NONE);
601 add_trace("interface", NULL, "%s", ifname);
608 if (!interface->extension)
610 /* found non extension */
611 trace_header("CHANNEL SELECTION (found non extension interface)", DIRECTION_NONE);
612 add_trace("interface", NULL, "%s", interface->name);
618 interface = interface->next;
622 /* see if interface has ports */
623 if (!interface->ifport)
626 trace_header("CHANNEL SELECTION (active ports, skipping)", DIRECTION_NONE);
627 add_trace("interface", NULL, "%s", interface->name);
629 interface = interface->next;
633 /* select port by algorithm */
634 ifport_start = interface->ifport;
636 if (interface->hunt == HUNT_ROUNDROBIN)
638 while(ifport_start->next && index<interface->hunt_next)
640 ifport_start = ifport_start->next;
643 trace_header("CHANNEL SELECTION (starting round-robin)", DIRECTION_NONE);
644 add_trace("port", NULL, "%d", ifport_start->portnum);
645 add_trace("position", NULL, "%d", index);
650 ifport = ifport_start;
653 /* see if port is available */
654 if (!ifport->mISDNport)
656 trace_header("CHANNEL SELECTION (port not available, skipping)", DIRECTION_NONE);
657 add_trace("port", NULL, "%d", ifport->portnum);
658 add_trace("position", NULL, "%d", index);
662 mISDNport = ifport->mISDNport;
664 /* see if port is administratively blocked */
667 trace_header("CHANNEL SELECTION (port blocked by admin, skipping)", DIRECTION_NONE);
668 add_trace("port", NULL, "%d", ifport->portnum);
669 add_trace("position", NULL, "%d", index);
674 /* see if link is up on PTP*/
675 if (mISDNport->l2hold && !mISDNport->l2link)
677 trace_header("CHANNEL SELECTION (port's layer 2 is down, skipping)", DIRECTION_NONE);
678 add_trace("port", NULL, "%d", ifport->portnum);
679 add_trace("position", NULL, "%d", index);
684 /* check for channel form selection list */
686 selchannel = ifport->out_channel;
689 switch(selchannel->channel)
691 case CHANNEL_FREE: /* free channel */
692 if (mISDNport->b_reserved >= mISDNport->b_num)
693 break; /* all channel in use or reserverd */
696 while(i < mISDNport->b_num)
698 if (mISDNport->b_port[i] == NULL)
700 *channel = i+1+(i>=15);
701 trace_header("CHANNEL SELECTION (selecting free channel)", DIRECTION_NONE);
702 add_trace("port", NULL, "%d", ifport->portnum);
703 add_trace("position", NULL, "%d", index);
704 add_trace("channel", NULL, "%d", *channel);
712 trace_header("CHANNEL SELECTION (no channel is 'free')", DIRECTION_NONE);
713 add_trace("port", NULL, "%d", ifport->portnum);
714 add_trace("position", NULL, "%d", index);
718 case CHANNEL_ANY: /* don't ask for channel */
719 if (mISDNport->b_reserved >= mISDNport->b_num)
721 trace_header("CHANNEL SELECTION (cannot ask for 'any' channel, all reserved)", DIRECTION_NONE);
722 add_trace("port", NULL, "%d", ifport->portnum);
723 add_trace("position", NULL, "%d", index);
724 add_trace("total", NULL, "%d", mISDNport->b_num);
725 add_trace("reserved", NULL, "%d", mISDNport->b_reserved);
727 break; /* all channel in use or reserverd */
729 trace_header("CHANNEL SELECTION (using 'any' channel)", DIRECTION_NONE);
730 add_trace("port", NULL, "%d", ifport->portnum);
731 add_trace("position", NULL, "%d", index);
733 *channel = CHANNEL_ANY;
736 case CHANNEL_NO: /* call waiting */
737 trace_header("CHANNEL SELECTION (using 'no' channel, call-waiting)", DIRECTION_NONE);
738 add_trace("port", NULL, "%d", ifport->portnum);
739 add_trace("position", NULL, "%d", index);
741 *channel = CHANNEL_NO;
745 if (selchannel->channel<1 || selchannel->channel==16)
747 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
748 add_trace("port", NULL, "%d", ifport->portnum);
749 add_trace("position", NULL, "%d", index);
750 add_trace("channel", NULL, "%d", selchannel->channel);
752 break; /* invalid channels */
754 i = selchannel->channel-1-(selchannel->channel>=17);
755 if (i >= mISDNport->b_num)
757 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
758 add_trace("port", NULL, "%d", ifport->portnum);
759 add_trace("position", NULL, "%d", index);
760 add_trace("channel", NULL, "%d", selchannel->channel);
761 add_trace("channels", NULL, "%d", mISDNport->b_num);
763 break; /* channel not in port */
765 if (mISDNport->b_port[i] == NULL)
767 *channel = selchannel->channel;
768 trace_header("CHANNEL SELECTION (selecting given channel)", DIRECTION_NONE);
769 add_trace("port", NULL, "%d", ifport->portnum);
770 add_trace("position", NULL, "%d", index);
771 add_trace("channel", NULL, "%d", *channel);
778 break; /* found channel */
779 selchannel = selchannel->next;
782 /* if channel was found, return mISDNport and channel */
785 /* setting next port to start next time */
786 if (interface->hunt == HUNT_ROUNDROBIN)
791 interface->hunt_next = index;
797 trace_header("CHANNEL SELECTION (skipping, no channel found)", DIRECTION_NONE);
798 add_trace("port", NULL, "%d", ifport->portnum);
799 add_trace("position", NULL, "%d", index);
803 /* go next port, until all ports are checked */
805 ifport = ifport->next;
809 ifport = interface->ifport;
811 if (ifport != ifport_start)
815 interface = interface->next;
819 return(NULL); /* no port found */
822 /* outgoing setup to port(s)
823 * ports will be created and a setup is sent if everything is ok. otherwhise
824 * the endpoint is destroyed.
826 void EndpointAppPBX::out_setup(void)
828 struct dialing_info dialinginfo;
830 // class pdss1 *pdss1;
831 struct port_list *portlist;
832 struct lcr_msg *message;
834 int cause = CAUSE_RESSOURCEUNAVAIL;
837 struct mISDNport *mISDNport;
840 class EndpointAppPBX *atemp;
841 // char allowed_ports[256];
843 char ifname[sizeof(e_ext.interfaces)],
845 struct port_settings port_settings;
849 /* create settings for creating port */
850 memset(&port_settings, 0, sizeof(port_settings));
852 SCPY(port_settings.tones_dir, e_ext.tones_dir);
854 SCPY(port_settings.tones_dir, options.tones_dir);
855 port_settings.no_seconds = e_ext.no_seconds;
857 /* NOTE: currently the try_card feature is not supported. it should be used later to try another card, if the outgoing call fails on one port */
859 /* check what dialinginfo.itype we got */
860 switch(e_dialinginfo.itype)
862 /* *********************** call to extension or vbox */
863 case INFO_ITYPE_ISDN_EXTENSION:
864 /* check if we deny incoming calls when we use an extension */
865 if (e_ext.noknocking)
867 atemp = apppbx_first;
871 if (!strcmp(atemp->e_ext.number, e_ext.number))
877 PERROR("EPOINT(%d) noknocking and currently a call\n", ea_endpoint->ep_serial);
878 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYSPE_ join, port */
879 return; /* must exit here */
882 /* FALL THROUGH !!!! */
883 case INFO_ITYPE_VBOX:
884 /* get dialed extension's info */
885 // SCPY(exten, e_dialinginfo.id);
886 // if (strchr(exten, ','))
887 // *strchr(exten, ',') = '\0';
888 // if (!read_extension(&e_ext, exten))
889 if (!read_extension(&e_ext, e_dialinginfo.id))
891 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) extension %s not configured\n", ea_endpoint->ep_serial, e_dialinginfo.id);
892 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
893 return; /* must exit here */
896 if (e_dialinginfo.itype == INFO_ITYPE_VBOX)
898 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing directly to VBOX\n", ea_endpoint->ep_serial);
903 /* string from unconditional call forward (cfu) */
907 /* present to forwarded party */
908 if (e_ext.anon_ignore && e_callerinfo.id[0])
910 e_callerinfo.present = INFO_PRESENT_ALLOWED;
912 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
916 /* string from busy call forward (cfb) */
920 class EndpointAppPBX *checkapp = apppbx_first;
923 if (checkapp != this) /* any other endpoint except our own */
925 if (!strcmp(checkapp->e_ext.number, e_ext.number))
927 /* present to forwarded party */
928 if (e_ext.anon_ignore && e_callerinfo.id[0])
930 e_callerinfo.present = INFO_PRESENT_ALLOWED;
932 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
936 checkapp = checkapp->next;
940 /* string from no-response call forward (cfnr) */
944 /* when cfnr is done, out_setup() will setup the call */
947 /* present to forwarded party */
948 if (e_ext.anon_ignore && e_callerinfo.id[0])
950 e_callerinfo.present = INFO_PRESENT_ALLOWED;
954 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
956 e_cfnr_release = now + e_ext.cfnr_delay;
957 e_cfnr_call = now + e_ext.cfnr_delay + 1; /* call one second after release */
958 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) setting time for call-forward-busy to %s with delay %ld.\n", ea_endpoint->ep_serial, e_ext.cfnr, e_ext.cfnr_delay);
962 /* call to all internal interfaces */
963 p = e_ext.interfaces;
964 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) generating multiple joins for extension %s to interfaces %s\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
968 while(*p!=',' && *p!='\0')
973 /* found interface */
974 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
975 /* hunt for mISDNport and create Port */
976 mISDNport = hunt_port(ifname, &channel);
979 trace_header("INTERFACE (not found or busy)", DIRECTION_NONE);
980 add_trace("interface", NULL, "%s", ifname);
984 /* creating INTERNAL port */
985 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
986 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force);
988 FATAL("No memory for DSS1 Port instance\n");
989 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
990 memset(&dialinginfo, 0, sizeof(dialinginfo));
991 SCPY(dialinginfo.id, e_dialinginfo.id);
992 dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
993 dialinginfo.ntype = e_dialinginfo.ntype;
994 /* create port_list relation */
995 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
998 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1000 goto check_anycall_intern;
1002 /* directory.list */
1003 if (e_callerinfo.id[0] && e_ext.display_name)
1005 dirname = parse_directory(e_callerinfo.id, e_callerinfo.ntype);
1007 SCPY(e_callerinfo.name, dirname);
1009 // dss1 = (class Pdss1 *)port;
1011 //printf("INTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1012 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1013 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1014 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1015 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1016 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1017 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1018 //terminal if (e_dialinginfo.id)
1019 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1020 /* handle restricted caller ids */
1021 apply_callerid_restriction(&e_ext, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
1022 apply_callerid_restriction(&e_ext, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, 0, message->param.setup.redirinfo.extension, NULL);
1023 /* display callerid if desired for extension */
1024 SCPY(message->param.setup.callerinfo.display, apply_callerid_display(message->param.setup.callerinfo.id, message->param.setup.callerinfo.itype, message->param.setup.callerinfo.ntype, message->param.setup.callerinfo.present, message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name));
1025 //printf("\n\ndisplay = %s\n\n\n",message->param.setup.callerinfo.display);
1026 /* use cnip, if enabld */
1027 // if (!e_ext.centrex)
1028 // message->param.setup.callerinfo.name[0] = '\0';
1029 /* screen clip if prefix is required */
1030 if (message->param.setup.callerinfo.id[0] && e_ext.clip_prefix[0])
1032 SCPY(message->param.setup.callerinfo.id, e_ext.clip_prefix);
1033 SCAT(message->param.setup.callerinfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype, options.national, options.international));
1034 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1036 /* use internal caller id */
1037 if (e_callerinfo.extension[0] && (message->param.setup.callerinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
1039 SCPY(message->param.setup.callerinfo.id, e_callerinfo.extension);
1040 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1042 message_put(message);
1043 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1047 /* string from parallel call forward (cfp) */
1051 if (e_ext.anon_ignore && e_callerinfo.id[0])
1053 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1057 vbox_only: /* entry point for answering machine only */
1058 cfu_only: /* entry point for cfu */
1059 cfb_only: /* entry point for cfb */
1060 cfnr_only: /* entry point for cfnr */
1061 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call extension %s for external destiantion(s) '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
1066 /* only if vbox should be dialed, and terminal is given */
1067 if (!strcmp(p, "vbox") && e_ext.number[0])
1069 /* go to the end of p */
1072 /* answering vbox call */
1073 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) answering machine\n", ea_endpoint->ep_serial);
1075 if (!(port = new VBoxPort(PORT_TYPE_VBOX_OUT, &port_settings)))
1076 FATAL("No memory for VBOX Port instance\n");
1077 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocated port %s\n", ea_endpoint->ep_serial, port->p_name);
1078 UCPY(cfp, e_ext.number); /* cfp or any other direct forward/vbox */
1082 while(*p!=',' && *p!='\0')
1087 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cfp external %s\n", ea_endpoint->ep_serial, cfp);
1088 /* hunt for mISDNport and create Port */
1089 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1092 /* creating EXTERNAL port*/
1093 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1094 if (!(port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force)))
1095 FATAL("No memory for DSS1 Port instance\n");
1096 earlyb = mISDNport->earlyb;
1100 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1101 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1107 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port found or created, which is idle.\n", ea_endpoint->ep_serial);
1108 goto check_anycall_intern;
1110 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found or created port %s\n", ea_endpoint->ep_serial, port->p_name);
1111 memset(&dialinginfo, 0, sizeof(dialinginfo));
1112 SCPY(dialinginfo.id, cfp);
1113 dialinginfo.itype = INFO_ITYPE_ISDN;
1114 dialinginfo.ntype = e_dialinginfo.ntype;
1115 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
1118 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1120 goto check_anycall_intern;
1122 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1123 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1124 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1125 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1126 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1127 /* if clip is hidden */
1128 if (e_ext.clip==CLIP_HIDE && port->p_type!=PORT_TYPE_VBOX_OUT)
1130 SCPY(message->param.setup.callerinfo.id, e_ext.callerid);
1131 SCPY(message->param.setup.callerinfo.extension, e_ext.number);
1132 message->param.setup.callerinfo.ntype = e_ext.callerid_type;
1133 message->param.setup.callerinfo.present = e_ext.callerid_present;
1135 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1136 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1137 //terminal if (e_dialinginfo.id)
1138 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1139 /* handle restricted caller ids */
1140 apply_callerid_restriction(&e_ext, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
1141 apply_callerid_restriction(&e_ext, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, 0, message->param.setup.redirinfo.extension, NULL);
1142 /* display callerid if desired for extension */
1143 SCPY(message->param.setup.callerinfo.display, apply_callerid_display(message->param.setup.callerinfo.id, message->param.setup.callerinfo.itype, message->param.setup.callerinfo.ntype, message->param.setup.callerinfo.present, message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name));
1144 message_put(message);
1145 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1149 check_anycall_intern:
1150 /* now we have all ports created */
1153 trace_header("INTERFACE (no extension's interface)", DIRECTION_NONE);
1155 if (!ea_endpoint->ep_join_id)
1157 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1158 return; /* must exit here */
1162 /* *********************** external call */
1164 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id);
1165 /* call to extenal interfaces */
1166 p = e_dialinginfo.id;
1170 while(*p!=',' && *p!='\0')
1171 SCCAT(number, *p++);
1175 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to number '%s' interface '%s'\n", ea_endpoint->ep_serial, number, e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1176 /* hunt for mISDNport and create Port */
1177 /* hunt for mISDNport and create Port */
1178 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1181 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1182 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1184 goto check_anycall_extern;
1186 /* creating EXTERNAL port*/
1187 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1188 if (!(port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force)))
1189 FATAL("No memory for DSS1 Port instance\n");
1190 earlyb = mISDNport->earlyb;
1191 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
1192 memset(&dialinginfo, 0, sizeof(dialinginfo));
1193 SCPY(dialinginfo.id, number);
1194 dialinginfo.itype = INFO_ITYPE_ISDN;
1195 dialinginfo.ntype = e_dialinginfo.ntype;
1196 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
1199 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1201 goto check_anycall_extern;
1203 // dss1 = (class Pdss1 *)port;
1204 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1205 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1206 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1207 SCPY(message->param.setup.dialinginfo.id, number);
1208 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1209 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1210 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1211 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1212 //terminal if (e_dialinginfo.id)
1213 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1214 /* handle restricted caller ids */
1215 apply_callerid_restriction(&e_ext, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
1216 apply_callerid_restriction(&e_ext, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, 0, message->param.setup.redirinfo.extension, NULL);
1217 /* display callerid if desired for extension */
1218 SCPY(message->param.setup.callerinfo.display, apply_callerid_display(message->param.setup.callerinfo.id, message->param.setup.callerinfo.itype, message->param.setup.callerinfo.ntype, message->param.setup.callerinfo.present, message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name));
1219 message_put(message);
1220 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1224 check_anycall_extern:
1225 /* now we have all ports created */
1228 trace_header("INTERFACE (no free ports found)", DIRECTION_NONE);
1230 if (!ea_endpoint->ep_join_id)
1232 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1233 return; /* must exit here */
1241 /* handler for endpoint
1245 int EndpointAppPBX::handler(void)
1247 if (e_crypt_state!=CM_ST_NULL)
1252 /* process answering machine (play) handling */
1255 if (e_action->index == ACTION_VBOX_PLAY)
1258 /* process action timeout */
1259 if (e_action_timeout)
1260 if (now_d >= e_action_timeout)
1262 if (e_state!=EPOINT_STATE_CONNECT)
1265 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current action timed out.\n", ea_endpoint->ep_serial);
1266 e_multipoint_cause = 0;
1267 e_multipoint_location = 0;
1268 new_state(EPOINT_STATE_IN_OVERLAP);
1271 return(1); /* we must exit, because our endpoint might be gone */
1273 e_action_timeout = 0;
1276 /* process action timeout */
1277 if (e_match_timeout)
1278 if (now_d >= e_match_timeout)
1281 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we got a match timeout.\n", ea_endpoint->ep_serial);
1283 return(1); /* we must exit, because our endpoint might be gone */
1288 /* process redialing (epoint redials to port) */
1291 if (now_d >= e_redial)
1294 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial.\n", ea_endpoint->ep_serial);
1296 new_state(EPOINT_STATE_OUT_SETUP);
1297 /* call special setup routine */
1304 /* process powerdialing (epoint redials to epoint) */
1305 if (e_powerdialing > 0)
1307 if (now_d >= e_powerdialing)
1309 e_powerdialing = -1; /* leave power dialing on */
1310 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial of powerdial.\n", ea_endpoint->ep_serial);
1313 e_ruleset = ruleset_main;
1315 e_rule = e_ruleset->rule_first;
1317 new_state(EPOINT_STATE_IN_OVERLAP);
1323 /* process call forward no response */
1326 struct port_list *portlist;
1327 struct lcr_msg *message;
1329 if (now >= e_cfnr_release)
1331 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-no-response time has expired, hanging up.\n", ea_endpoint->ep_serial);
1334 /* release all ports */
1335 while((portlist = ea_endpoint->ep_portlist))
1337 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1338 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
1339 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1340 message_put(message);
1341 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1342 ea_endpoint->free_portlist(portlist);
1345 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1346 message->param.audiopath = 0;
1347 message_put(message);
1348 /* indicate no patterns */
1349 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1350 message_put(message);
1351 /* set setup state, since we have no response from the new join */
1352 new_state(EPOINT_STATE_OUT_SETUP);
1357 if (now >= e_cfnr_call)
1359 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-busy time has expired, calling the forwarded number: %s.\n", ea_endpoint->ep_serial, e_ext.cfnr);
1365 /* handle connection to user */
1366 if (e_state == EPOINT_STATE_IDLE)
1368 /* epoint is idle, check callback */
1370 if (now_d >= e_callback)
1372 e_callback = 0; /* done with callback */
1373 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting callback.\n", ea_endpoint->ep_serial);
1374 new_state(EPOINT_STATE_OUT_SETUP);
1380 /* check for password timeout */
1382 if (e_action->index==ACTION_PASSWORD || e_action->index==ACTION_PASSWORD_WRITE)
1384 struct port_list *portlist;
1386 if (now >= e_password_timeout)
1388 e_ruleset = ruleset_main;
1390 e_rule = e_ruleset->rule_first;
1392 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) password timeout %s\n", ea_endpoint->ep_serial, e_extdialing);
1393 trace_header("PASSWORD timeout", DIRECTION_NONE);
1395 e_connectedmode = 0;
1397 new_state(EPOINT_STATE_OUT_DISCONNECT);
1398 portlist = ea_endpoint->ep_portlist;
1401 message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
1402 set_tone(portlist, "cause_10");
1412 /* doing a hookflash */
1413 void EndpointAppPBX::hookflash(void)
1417 /* be sure that we are active */
1419 e_tx_state = NOTIFY_STATE_ACTIVE;
1421 trace_header("HOOKFLASH DTMF", DIRECTION_NONE);
1423 if (ea_endpoint->ep_use > 1)
1425 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot hooflash while child process is running.\n", ea_endpoint->ep_serial);
1428 /* dialtone after pressing the hash key */
1429 process_hangup(e_join_cause, e_join_location);
1430 e_multipoint_cause = 0;
1431 e_multipoint_location = 0;
1432 port = find_port_id(ea_endpoint->ep_portlist->port_id);
1435 port->set_echotest(0);
1437 if (ea_endpoint->ep_join_id)
1439 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1441 e_ruleset = ruleset_main;
1443 e_rule = e_ruleset->rule_first;
1445 new_state(EPOINT_STATE_IN_OVERLAP);
1446 e_connectedmode = 1;
1447 SCPY(e_dialinginfo.id, e_ext.prefix);
1448 e_extdialing = e_dialinginfo.id;
1450 if (e_dialinginfo.id[0])
1452 set_tone(ea_endpoint->ep_portlist, "dialing");
1456 set_tone(ea_endpoint->ep_portlist, "dialpbx");
1463 /* messages from port
1465 /* port MESSAGE_SETUP */
1466 void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, union parameter *param)
1468 struct lcr_msg *message;
1470 int writeext; /* flags need to write extension after modification */
1472 struct interface *interface;
1474 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1476 portlist->port_type = param->setup.port_type;
1477 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
1478 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
1479 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
1480 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
1481 // e_dtmf = param->setup.dtmf;
1482 /* screen incoming caller id */
1483 interface = interface_first;
1486 if (!strcmp(e_callerinfo.interface, interface->name))
1490 interface = interface->next;
1493 do_screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface);
1495 /* process extension */
1496 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1498 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is extension\n", ea_endpoint->ep_serial);
1499 /* port makes call from extension */
1500 SCPY(e_callerinfo.extension, e_callerinfo.id);
1501 SCPY(e_ext.number, e_callerinfo.extension);
1502 SCPY(e_extension_interface, e_callerinfo.interface);
1505 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is external or voip\n", ea_endpoint->ep_serial);
1508 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1510 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1512 /* get extension's info about caller */
1513 if (!read_extension(&e_ext, e_ext.number))
1515 /* extension doesn't exist */
1516 trace_header("EXTENSION (not created)", DIRECTION_IN);
1517 add_trace("extension", NULL, "%s", e_ext.number);
1519 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
1520 new_state(EPOINT_STATE_OUT_DISCONNECT);
1521 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
1522 e_ext.number[0] = '\0'; /* no terminal */
1527 /* put prefix (next) in front of e_dialinginfo.id */
1530 SPRINT(buffer, "%s%s", e_ext.next, e_dialinginfo.id);
1531 SCPY(e_dialinginfo.id, buffer);
1532 e_ext.next[0] = '\0';
1534 } else if (e_ext.prefix[0])
1536 SPRINT(buffer, "%s%s", e_ext.prefix, e_dialinginfo.id);
1537 SCPY(e_dialinginfo.id, buffer);
1540 /* screen caller id by extension's config */
1541 e_callerinfo.screen = INFO_SCREEN_NETWORK;
1543 SCPY(e_callerinfo.name, e_ext.name);
1544 /* use caller id (or if exist: id_next_call) for this call */
1545 if (e_ext.id_next_call_present >= 0)
1547 SCPY(e_callerinfo.id, e_ext.id_next_call);
1548 /* if we restrict the pesentation */
1549 if (e_ext.id_next_call_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1550 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1551 else e_callerinfo.present = e_ext.id_next_call_present;
1552 e_callerinfo.ntype = e_ext.id_next_call_type;
1553 e_ext.id_next_call_present = -1;
1557 SCPY(e_callerinfo.id, e_ext.callerid);
1558 /* if we restrict the pesentation */
1559 if (e_ext.callerid_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1560 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1561 else e_callerinfo.present = e_ext.callerid_present;
1562 e_callerinfo.ntype = e_ext.callerid_type;
1565 /* extension is written */
1567 write_extension(&e_ext, e_ext.number);
1569 /* set volume of rx and tx */
1570 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1571 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
1573 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
1574 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
1575 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
1576 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
1577 message_put(message);
1580 /* start recording if enabled */
1581 if (e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO))
1583 /* check if we are a terminal */
1584 if (e_ext.number[0] == '\0')
1585 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
1588 port = find_port_id(portlist->port_id);
1590 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
1595 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from external port\n", ea_endpoint->ep_serial);
1596 /* no terminal identification */
1597 e_ext.number[0] = '\0';
1598 e_extension_interface[0] = '\0';
1599 memset(&e_ext, 0, sizeof(e_ext));
1600 e_ext.rights = 4; /* right to dial internat */
1604 e_ruleset = ruleset_main;
1606 e_rule = e_ruleset->rule_first;
1608 e_extdialing = e_dialinginfo.id;
1609 new_state(EPOINT_STATE_IN_SETUP);
1610 if (e_dialinginfo.id[0])
1612 set_tone(portlist, "dialing");
1615 if (e_ext.number[0])
1616 set_tone(portlist, "dialpbx");
1618 set_tone(portlist, "dialtone");
1621 if (e_state == EPOINT_STATE_IN_SETUP)
1623 /* request MORE info, if not already at higher state */
1624 new_state(EPOINT_STATE_IN_OVERLAP);
1625 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_OVERLAP);
1626 message_put(message);
1627 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1631 /* port MESSAGE_INFORMATION */
1632 void EndpointAppPBX::port_information(struct port_list *portlist, int message_type, union parameter *param)
1634 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1636 /* ignore information message without digit information */
1637 if (!param->information.id[0])
1642 /* turn off dtmf detection, in case dtmf is sent with keypad information */
1645 trace_header("DTMF (disabling due to keypad)", DIRECTION_IN);
1650 /* if vbox_play is done, the information are just used as they come */
1652 if (e_action->index == ACTION_VBOX_PLAY)
1654 /* concat dialing string */
1655 SCAT(e_dialinginfo.id, param->information.id);
1660 /* keypad when disconnect but in connected mode */
1661 if (e_state==EPOINT_STATE_OUT_DISCONNECT && e_connectedmode)
1663 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received after disconnect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1664 /* processing keypad function */
1665 if (param->information.id[0] == '0')
1672 /* keypad when connected */
1673 if (e_state == EPOINT_STATE_CONNECT)
1675 if (e_ext.keypad || e_enablekeypad)
1677 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1678 /* processing keypad function */
1679 if (param->information.id[0] == '0')
1683 if (param->information.id[0])
1684 keypad_function(param->information.id[0]);
1687 if (e_ext.number[0])
1688 trace_header("KEYPAD (not enabled by extension's settings)", DIRECTION_IN);
1690 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1695 if (e_state != EPOINT_STATE_IN_OVERLAP)
1697 if (e_ext.number[0])
1698 trace_header("KEYPAD (ignored, not connected and not dialing)", DIRECTION_IN);
1700 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1704 if (!param->information.id[0])
1706 if (e_dialinginfo.id[0]=='\0' && !e_action)
1708 set_tone(portlist, "dialing");
1711 if (e_action->index==ACTION_OUTDIAL
1712 || e_action->index==ACTION_EXTERNAL
1713 || e_action->index==ACTION_REMOTE)
1716 set_tone(portlist, "dialing");
1717 else if (!e_extdialing[0])
1718 set_tone(portlist, "dialing");
1720 /* concat dialing string */
1721 SCAT(e_dialinginfo.id, param->information.id);
1725 /* port MESSAGE_DTMF */
1726 void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
1728 /* only if dtmf detection is enabled */
1731 trace_header("DTMF (disabled)", DIRECTION_IN);
1735 trace_header("DTMF", DIRECTION_IN);
1736 add_trace("digit", NULL, "%c", param->dtmf);
1740 NOTE: vbox is now handled due to overlap state
1741 /* if vbox_play is done, the dtmf digits are just used as they come */
1743 if (e_action->index == ACTION_VBOX_PLAY)
1745 /* concat dialing string */
1746 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id))
1748 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1749 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1752 /* continue to process *X# sequences */
1756 /* check for *X# sequence */
1757 if (e_state == EPOINT_STATE_CONNECT)
1759 if (e_dtmf_time+3 < now)
1761 /* the last digit was too far in the past to be a sequence */
1762 if (param->dtmf == '*')
1763 /* only start is allowed in the sequence */
1769 /* we have a sequence of digits, see what we got */
1770 if (param->dtmf == '*')
1772 else if (param->dtmf>='0' && param->dtmf<='9')
1774 /* we need to have a star before we receive the digit of the sequence */
1775 if (e_dtmf_last == '*')
1776 e_dtmf_last = param->dtmf;
1777 } else if (param->dtmf == '#')
1780 if (e_dtmf_last>='0' && e_dtmf_last<='9')
1782 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf sequence *%c# detected.\n", ea_endpoint->ep_serial, e_dtmf_last);
1783 if (e_dtmf_last == '0')
1788 /* processing keypad function */
1790 keypad_function(e_dtmf_last);
1796 /* set last time of dtmf */
1801 /* check for ## hookflash during dialing */
1803 if (e_action->index==ACTION_PASSWORD
1804 || e_action->index==ACTION_PASSWORD_WRITE)
1806 if (param->dtmf=='#') /* current digit is '#' */
1808 if (e_state==EPOINT_STATE_IN_DISCONNECT
1809 || (e_state!=EPOINT_STATE_CONNECT && e_dtmf_time+3>=now && e_dtmf_last=='#')) /* when disconnected, just #. when dialing, ##. */
1826 /* dialing using dtmf digit */
1827 if (e_state==EPOINT_STATE_IN_OVERLAP)// && e_state==e_connectedmode)
1829 if (e_dialinginfo.id[0]=='\0' && !e_action)
1831 set_tone(portlist, "dialing");
1833 /* concat dialing string */
1834 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id))
1836 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1837 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1843 /* port MESSAGE_CRYPT */
1844 void EndpointAppPBX::port_crypt(struct port_list *portlist, int message_type, union parameter *param)
1846 /* send crypt response to cryptman */
1847 if (param->crypt.type == CR_MESSAGE_IND)
1848 cryptman_msg2man(param->crypt.data, param->crypt.len);
1850 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
1853 /* port MESSAGE_OVERLAP */
1854 void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, union parameter *param)
1856 struct lcr_msg *message;
1858 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1860 /* signal to call tool */
1861 admin_call_response(e_adminid, ADMIN_CALL_SETUP_ACK, "", 0, 0, 0);
1863 if (e_dialing_queue[0] && portlist)
1865 /* send what we have not dialed yet, because we had no setup complete */
1866 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing pending digits: '%s'\n", ea_endpoint->ep_serial, e_dialing_queue);
1867 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
1868 SCPY(message->param.information.id, e_dialing_queue);
1869 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
1870 message_put(message);
1871 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
1872 e_dialing_queue[0] = '\0';
1874 /* check if pattern is available */
1875 if (!ea_endpoint->ep_portlist->next && portlist->early_b) /* one port_list relation and tones available */
1877 /* indicate patterns */
1878 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1879 message_put(message);
1881 /* connect audio, if not already */
1882 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1883 message->param.audiopath = 1;
1884 message_put(message);
1887 /* indicate no patterns */
1888 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1889 message_put(message);
1891 /* disconnect audio, if not already */
1892 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1893 message->param.audiopath = 0;
1894 message_put(message);
1896 new_state(EPOINT_STATE_OUT_OVERLAP);
1897 /* if we are in a join */
1898 if (ea_endpoint->ep_join_id)
1900 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1901 memcpy(&message->param, param, sizeof(union parameter));
1902 message_put(message);
1906 /* port MESSAGE_PROCEEDING */
1907 void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_type, union parameter *param)
1909 struct lcr_msg *message;
1911 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1913 /* signal to call tool */
1914 admin_call_response(e_adminid, ADMIN_CALL_PROCEEDING, "", 0, 0, 0);
1916 e_state = EPOINT_STATE_OUT_PROCEEDING;
1917 /* check if pattern is availatle */
1918 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
1920 /* indicate patterns */
1921 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1922 message_put(message);
1924 /* connect audio, if not already */
1925 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1926 message->param.audiopath = 1;
1927 message_put(message);
1930 /* indicate no patterns */
1931 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1932 message_put(message);
1934 /* disconnect audio, if not already */
1935 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1936 message->param.audiopath = 0;
1937 message_put(message);
1939 /* if we are in a call */
1940 if (ea_endpoint->ep_join_id)
1942 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1943 memcpy(&message->param, param, sizeof(union parameter));
1944 message_put(message);
1948 /* port MESSAGE_ALERTING */
1949 void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type, union parameter *param)
1951 struct lcr_msg *message;
1953 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1955 /* signal to call tool */
1956 admin_call_response(e_adminid, ADMIN_CALL_ALERTING, "", 0, 0, 0);
1959 // set_tone(portlist, "hold");
1961 new_state(EPOINT_STATE_OUT_ALERTING);
1962 /* check if pattern is available */
1963 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
1965 /* indicate patterns */
1966 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1967 message_put(message);
1969 /* connect audio, if not already */
1970 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1971 message->param.audiopath = 1;
1972 message_put(message);
1975 /* indicate no patterns */
1976 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1977 message_put(message);
1979 /* disconnect audio, if not already */
1980 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1981 message->param.audiopath = 0;
1982 message_put(message);
1984 /* if we are in a call */
1985 if (ea_endpoint->ep_join_id)
1987 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1988 memcpy(&message->param, param, sizeof(union parameter));
1989 message_put(message);
1993 /* port MESSAGE_CONNECT */
1994 void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, union parameter *param)
1996 struct lcr_msg *message;
1998 unsigned int port_id = portlist->port_id;
1999 struct port_list *tportlist;
2001 struct interface *interface;
2003 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2005 /* signal to call tool */
2006 admin_call_response(e_adminid, ADMIN_CALL_CONNECT, numberrize_callerinfo(param->connectinfo.id,param->connectinfo.ntype, options.national, options.international), 0, 0, 0);
2008 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_connectinfo));
2009 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (start)\n", ea_endpoint->ep_serial);
2010 while(ea_endpoint->ep_portlist->next) /* as long as we have at least two ports */
2012 tportlist = ea_endpoint->ep_portlist;
2013 if (tportlist->port_id == port_id) /* if the first portlist is the calling one, the second must be a different one */
2014 tportlist = tportlist->next;
2015 if (tportlist->port_id == port_id)
2016 FATAL("EPOINT(%d) this should not happen since the portlist list must not have two links to the same port - exitting.\n");
2017 message = message_create(ea_endpoint->ep_serial, tportlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2018 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
2019 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2020 message_put(message);
2021 logmessage(message->type, &message->param, tportlist->port_id, DIRECTION_OUT);
2022 ea_endpoint->free_portlist(tportlist);
2024 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (end)\n", ea_endpoint->ep_serial);
2028 /* screen incoming connected id */
2029 interface = interface_first;
2032 if (!strcmp(e_connectinfo.interface, interface->name))
2036 interface = interface->next;
2039 do_screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface);
2041 /* screen connected name */
2043 SCPY(e_connectinfo.name, e_ext.name);
2045 /* add internal id to colp */
2046 SCPY(e_connectinfo.extension, e_ext.number);
2048 /* we store the connected port number */
2049 SCPY(e_extension_interface, e_connectinfo.interface);
2051 /* for internal and am calls, we get the extension's id */
2052 if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE)
2054 SCPY(e_connectinfo.id, e_ext.callerid);
2055 SCPY(e_connectinfo.extension, e_ext.number);
2056 e_connectinfo.itype = INFO_ITYPE_ISDN_EXTENSION;
2057 e_connectinfo.ntype = e_ext.callerid_type;
2058 e_connectinfo.present = e_ext.callerid_present;
2060 if (portlist->port_type==PORT_TYPE_VBOX_OUT)
2062 e_connectinfo.itype = INFO_ITYPE_VBOX;
2063 e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2066 new_state(EPOINT_STATE_CONNECT);
2068 /* set volume of rx and tx */
2069 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
2071 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2072 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2073 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
2074 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
2075 message_put(message);
2078 e_cfnr_call = e_cfnr_release = 0;
2079 if (e_ext.number[0])
2080 e_dtmf = 1; /* allow dtmf */
2083 /* other calls with no caller id (or not available for the extension) and force colp */
2084 if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE)
2086 e_connectinfo.present = INFO_PRESENT_NOTAVAIL;
2087 if (portlist->port_type==PORT_TYPE_DSS1_TE_OUT || portlist->port_type==PORT_TYPE_DSS1_NT_OUT) /* external extension answered */
2089 port = find_port_id(portlist->port_id);
2092 SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.id, &e_connectinfo.ntype, options.national, options.international));
2093 e_connectinfo.present = INFO_PRESENT_ALLOWED;
2098 /* send connect to join */
2099 if (ea_endpoint->ep_join_id)
2101 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2102 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
2103 message_put(message);
2105 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2106 message->param.audiopath = 1;
2107 message_put(message);
2108 } else if (!e_adminid)
2111 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have a callback, so we create a call with cbcaller: \"%s\".\n", ea_endpoint->ep_serial, e_cbcaller);
2112 SCPY(e_ext.number, e_cbcaller);
2113 new_state(EPOINT_STATE_IN_OVERLAP);
2114 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) callback from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2116 /* get extension's info about terminal */
2117 if (!read_extension(&e_ext, e_ext.number))
2119 /* extension doesn't exist */
2120 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2121 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
2122 new_state(EPOINT_STATE_OUT_DISCONNECT);
2123 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
2127 /* put prefix in front of e_cbdialing */
2128 SPRINT(buffer, "%s%s", e_ext.prefix, e_cbdialing);
2129 SCPY(e_dialinginfo.id, buffer);
2130 e_dialinginfo.itype = INFO_ITYPE_ISDN;
2131 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
2133 /* use caller id (or if exist: id_next_call) for this call */
2134 e_callerinfo.screen = INFO_SCREEN_NETWORK;
2135 SCPY(e_callerinfo.extension, e_ext.number);
2136 if (e_ext.id_next_call_present >= 0)
2138 SCPY(e_callerinfo.id, e_ext.id_next_call);
2139 e_callerinfo.present = e_ext.id_next_call_present;
2140 e_callerinfo.ntype = e_ext.id_next_call_type;
2141 e_ext.id_next_call_present = -1;
2142 /* extension is written */
2143 write_extension(&e_ext, e_ext.number);
2146 SCPY(e_callerinfo.id, e_ext.callerid);
2147 e_callerinfo.present = e_ext.callerid_present;
2148 e_callerinfo.ntype = e_ext.callerid_type;
2151 e_connectedmode = 1; /* dtmf-hangup & disconnect prevention */
2154 /* check if caller id is NOT authenticated */
2155 if (!parse_callbackauth(e_ext.number, &e_callbackinfo))
2157 /* make call state to enter password */
2158 new_state(EPOINT_STATE_IN_OVERLAP);
2159 e_action = &action_password_write;
2160 e_match_timeout = 0;
2161 e_match_to_action = NULL;
2162 e_dialinginfo.id[0] = '\0';
2163 e_extdialing = strchr(e_dialinginfo.id, '\0');
2164 e_password_timeout = now+20;
2168 /* incoming call (callback) */
2169 e_ruleset = ruleset_main;
2171 e_rule = e_ruleset->rule_first;
2173 e_extdialing = e_dialinginfo.id;
2174 if (e_dialinginfo.id[0])
2176 set_tone(portlist, "dialing");
2180 set_tone(portlist, "dialpbx");
2183 } else /* testcall */
2185 set_tone(portlist, "hold");
2188 /* start recording if enabled, not when answering machine answers */
2189 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))
2191 /* check if we are a terminal */
2192 if (e_ext.number[0] == '\0')
2193 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
2196 port = find_port_id(portlist->port_id);
2198 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
2203 /* port MESSAGE_DISCONNECT MESSAGE_RELEASE */
2204 void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
2206 struct lcr_msg *message;
2208 unsigned int port_id = portlist->port_id;
2212 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2214 /* signal to call tool */
2215 admin_call_response(e_adminid, (message_type==MESSAGE_DISCONNECT)?ADMIN_CALL_DISCONNECT:ADMIN_CALL_RELEASE, "", param->disconnectinfo.cause, param->disconnectinfo.location, 0);
2217 //#warning does this work? only disconnect when incoming port hat not already disconnected yet?
2218 if (e_state==EPOINT_STATE_IN_DISCONNECT && message_type!=MESSAGE_RELEASE)// || e_state==EPOINT_STATE_OUT_DISCONNECT || e_state==EPOINT_STATE_IDLE)
2220 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are already disconnected.\n", ea_endpoint->ep_serial);
2225 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);
2226 collect_cause(&e_multipoint_cause, &e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location);
2227 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new multipoint cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location);
2229 /* check if we have more than one portlist relation and we just ignore the disconnect */
2230 if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist->next)
2232 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the disconnect was from a multipoint call. we just release that relation.\n", ea_endpoint->ep_serial);
2233 portlist = ea_endpoint->ep_portlist;
2236 if (portlist->port_id == port_id)
2238 portlist = portlist->next;
2241 FATAL("EPOINT(%d) no portlist related to the calling port.\n", ea_endpoint->ep_serial);
2242 if (message_type != MESSAGE_RELEASE)
2244 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2245 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2246 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2247 message_put(message);
2248 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2250 ea_endpoint->free_portlist(portlist);
2251 return; /* one relation removed */
2253 if (e_state == EPOINT_STATE_CONNECT)
2255 /* use cause from port after connect */
2256 cause = param->disconnectinfo.cause;
2257 location = param->disconnectinfo.location;
2260 /* use multipoint cause if no connect yet */
2261 if (e_multipoint_cause)
2263 cause = e_multipoint_cause;
2264 location = e_multipoint_location;
2267 cause = CAUSE_NOUSER;
2268 location = LOCATION_PRIVATE_LOCAL;
2272 e_cfnr_call = e_cfnr_release = 0;
2274 /* process hangup */
2275 process_hangup(e_join_cause, e_join_location);
2276 e_multipoint_cause = 0;
2277 e_multipoint_location = 0;
2279 if (message_type == MESSAGE_DISCONNECT)
2281 /* tone to disconnected end */
2282 SPRINT(buffer, "cause_%02x", cause);
2283 if (ea_endpoint->ep_portlist)
2284 set_tone(ea_endpoint->ep_portlist, buffer);
2286 new_state(EPOINT_STATE_IN_DISCONNECT);
2289 if (ea_endpoint->ep_join_id)
2291 int haspatterns = 0;
2292 /* check if pattern is available */
2293 if (ea_endpoint->ep_portlist)
2294 if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->early_b)
2295 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
2296 && message_type != MESSAGE_RELEASE) // if we release, we are done
2300 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has patterns.\n", ea_endpoint->ep_serial);
2301 /* indicate patterns */
2302 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2303 message_put(message);
2304 /* connect audio, if not already */
2305 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2306 message->param.audiopath = 1;
2307 message_put(message);
2308 /* send disconnect */
2309 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2310 memcpy(&message->param, param, sizeof(union parameter));
2311 message_put(message);
2312 /* disable encryption if disconnected */
2313 //PERROR("REMOVE ME: state =%d, %d\n", e_crypt_state, e_crypt);
2315 cryptman_message(CI_DISCONNECT_IND, NULL, 0);
2319 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
2322 if (message_type == MESSAGE_RELEASE)
2323 ea_endpoint->free_portlist(portlist);
2324 release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, callcause, portcause */
2325 return; /* must exit here */
2328 /* port MESSAGE_TIMEOUT */
2329 void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type, union parameter *param)
2333 trace_header("TIMEOUT", DIRECTION_IN);
2334 message_type = MESSAGE_DISCONNECT;
2335 switch (param->state)
2337 case PORT_STATE_OUT_SETUP:
2338 case PORT_STATE_OUT_OVERLAP:
2339 add_trace("state", NULL, "outgoing setup/dialing");
2341 /* no user responding */
2342 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2343 return; /* must exit here */
2345 case PORT_STATE_IN_SETUP:
2346 case PORT_STATE_IN_OVERLAP:
2347 add_trace("state", NULL, "incoming setup/dialing");
2348 param->disconnectinfo.cause = CAUSE_INVALID; /* number incomplete */
2349 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2352 case PORT_STATE_OUT_PROCEEDING:
2353 add_trace("state", NULL, "outgoing proceeding");
2355 param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
2356 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2357 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2358 return; /* must exit here */
2360 case PORT_STATE_IN_PROCEEDING:
2361 add_trace("state", NULL, "incoming proceeding");
2362 param->disconnectinfo.cause = CAUSE_NOUSER;
2363 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL; /* no user responding */
2366 case PORT_STATE_OUT_ALERTING:
2367 add_trace("state", NULL, "outgoing alerting");
2369 param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
2370 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2371 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2372 return; /* must exit here */
2374 case PORT_STATE_CONNECT:
2375 add_trace("state", NULL, "connect");
2377 param->disconnectinfo.cause = CAUSE_NORMAL; /* normal */
2378 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2379 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2380 return; /* must exit here */
2382 case PORT_STATE_IN_ALERTING:
2383 add_trace("state", NULL, "incoming alerting");
2384 param->disconnectinfo.cause = CAUSE_NOANSWER;
2385 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2388 case PORT_STATE_IN_DISCONNECT:
2389 case PORT_STATE_OUT_DISCONNECT:
2390 add_trace("state", NULL, "disconnect");
2392 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
2393 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2394 return; /* must exit here */
2397 param->disconnectinfo.cause = 31; /* normal unspecified */
2398 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2401 /* release call, disconnect isdn */
2403 new_state(EPOINT_STATE_OUT_DISCONNECT);
2404 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2405 SCPY(e_tone, cause);
2408 set_tone(portlist, cause);
2409 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2410 portlist = portlist->next;
2412 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
2415 /* port MESSAGE_NOTIFY */
2416 void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, union parameter *param)
2418 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2420 struct lcr_msg *message;
2424 /* signal to call tool */
2425 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);
2426 if (param->notifyinfo.notify)
2428 e_rx_state = track_notify(e_rx_state, param->notifyinfo.notify);
2431 /* if we get notification from stack, local shows if we disabled/enabled audio stream */
2432 if (param->notifyinfo.local) switch(param->notifyinfo.notify)
2434 case INFO_NOTIFY_REMOTE_HOLD:
2435 case INFO_NOTIFY_USER_SUSPENDED:
2436 /* tell call about it */
2437 if (ea_endpoint->ep_join_id)
2439 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2440 message->param.audiopath = 0;
2441 message_put(message);
2445 case INFO_NOTIFY_REMOTE_RETRIEVAL:
2446 case INFO_NOTIFY_USER_RESUMED:
2447 /* set volume of rx and tx */
2448 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
2449 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
2452 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2453 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2454 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
2455 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
2456 message_put(message);
2458 /* set current tone */
2460 set_tone(portlist, e_tone);
2461 /* tell call about it */
2462 if (ea_endpoint->ep_join_id)
2464 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2465 message->param.audiopath = 1;
2466 message_put(message);
2471 /* get name of notify */
2472 switch(param->notifyinfo.notify)
2478 logtext = "USER_SUSPENDED";
2481 logtext = "BEARER_SERVICE_CHANGED";
2484 logtext = "USER_RESUMED";
2487 logtext = "CONFERENCE_ESTABLISHED";
2490 logtext = "CONFERENCE_DISCONNECTED";
2493 logtext = "OTHER_PARTY_ADDED";
2496 logtext = "ISOLATED";
2499 logtext = "REATTACHED";
2502 logtext = "OTHER_PARTY_ISOLATED";
2505 logtext = "OTHER_PARTY_REATTACHED";
2508 logtext = "OTHER_PARTY_SPLIT";
2511 logtext = "OTHER_PARTY_DISCONNECTED";
2514 logtext = "CONFERENCE_FLOATING";
2517 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
2520 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
2523 logtext = "CALL_IS_A_WAITING_CALL";
2526 logtext = "DIVERSION_ACTIVATED";
2529 logtext = "RESERVED_CT_1";
2532 logtext = "RESERVED_CT_2";
2535 logtext = "REVERSE_CHARGING";
2538 logtext = "REMOTE_HOLD";
2541 logtext = "REMOTE_RETRIEVAL";
2544 logtext = "CALL_IS_DIVERTING";
2547 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
2552 /* notify call if available */
2553 if (ea_endpoint->ep_join_id)
2555 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOTIFY);
2556 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
2557 message_put(message);
2562 /* port MESSAGE_FACILITY */
2563 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
2565 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2567 struct lcr_msg *message;
2569 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_FACILITY);
2570 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2571 message_put(message);
2574 /* port MESSAGE_SUSPEND */
2575 /* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
2576 void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
2578 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2580 /* epoint is now parked */
2581 ea_endpoint->ep_park = 1;
2582 memcpy(ea_endpoint->ep_park_callid, param->parkinfo.callid, sizeof(ea_endpoint->ep_park_callid));
2583 ea_endpoint->ep_park_len = (param->parkinfo.len>8)?8:param->parkinfo.len;
2585 /* remove port relation */
2586 ea_endpoint->free_portlist(portlist);
2589 /* port MESSAGE_RESUME */
2590 /* NOTE: before resume, the active-notification must be done in order to set call mixer */
2591 void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
2593 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2595 /* epoint is now resumed */
2596 ea_endpoint->ep_park = 0;
2601 /* port sends message to the endpoint
2603 void EndpointAppPBX::ea_message_port(unsigned int port_id, int message_type, union parameter *param)
2605 struct port_list *portlist;
2606 struct lcr_msg *message;
2608 portlist = ea_endpoint->ep_portlist;
2611 if (port_id == portlist->port_id)
2613 portlist = portlist->next;
2617 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);
2621 // PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
2622 switch(message_type)
2624 case MESSAGE_DATA: /* data from port */
2625 /* check if there is a call */
2626 if (!ea_endpoint->ep_join_id)
2628 /* continue if only one portlist */
2629 if (ea_endpoint->ep_portlist->next != NULL)
2631 /* forward message */
2632 message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2635 case MESSAGE_TONE_EOF: /* tone is end of file */
2636 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
2639 if (e_action->index == ACTION_VBOX_PLAY)
2643 if (e_action->index == ACTION_EFI)
2650 case MESSAGE_TONE_COUNTER: /* counter info received */
2651 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);
2653 if (e_action->index == ACTION_VBOX_PLAY)
2655 e_vbox_counter = param->counter.current;
2656 if (param->counter.max >= 0)
2657 e_vbox_counter_max = param->counter.max;
2661 /* PORT sends SETUP message */
2663 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);
2664 if (e_state!=EPOINT_STATE_IDLE)
2666 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
2669 port_setup(portlist, message_type, param);
2672 /* PORT sends INFORMATION message */
2673 case MESSAGE_INFORMATION: /* additional digits received */
2674 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);
2675 port_information(portlist, message_type, param);
2678 /* PORT sends FACILITY message */
2679 case MESSAGE_FACILITY:
2680 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2681 port_facility(portlist, message_type, param);
2684 /* PORT sends DTMF message */
2685 case MESSAGE_DTMF: /* dtmf digits received */
2686 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);
2687 port_dtmf(portlist, message_type, param);
2690 /* PORT sends CRYPT message */
2691 case MESSAGE_CRYPT: /* crypt response received */
2692 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) crypt response=%d\n", ea_endpoint->ep_serial, param->crypt.type);
2693 port_crypt(portlist, message_type, param);
2696 /* PORT sends MORE message */
2697 case MESSAGE_OVERLAP:
2698 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);
2699 if (e_state != EPOINT_STATE_OUT_SETUP)
2701 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);
2704 port_overlap(portlist, message_type, param);
2707 /* PORT sends PROCEEDING message */
2708 case MESSAGE_PROCEEDING: /* port is proceeding */
2709 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);
2710 if (e_state!=EPOINT_STATE_OUT_SETUP
2711 && e_state!=EPOINT_STATE_OUT_OVERLAP)
2713 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);
2716 port_proceeding(portlist, message_type, param);
2719 /* PORT sends ALERTING message */
2720 case MESSAGE_ALERTING:
2721 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);
2722 if (e_state!=EPOINT_STATE_OUT_SETUP
2723 && e_state!=EPOINT_STATE_OUT_OVERLAP
2724 && e_state!=EPOINT_STATE_OUT_PROCEEDING)
2726 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);
2729 port_alerting(portlist, message_type, param);
2732 /* PORT sends CONNECT message */
2733 case MESSAGE_CONNECT:
2734 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);
2735 if (e_state!=EPOINT_STATE_OUT_SETUP
2736 && e_state!=EPOINT_STATE_OUT_OVERLAP
2737 && e_state!=EPOINT_STATE_OUT_PROCEEDING
2738 && e_state!=EPOINT_STATE_OUT_ALERTING)
2740 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
2743 port_connect(portlist, message_type, param);
2746 /* PORT sends DISCONNECT message */
2747 case MESSAGE_DISCONNECT: /* port is disconnected */
2748 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);
2749 port_disconnect_release(portlist, message_type, param);
2752 /* PORT sends a RELEASE message */
2753 case MESSAGE_RELEASE: /* port releases */
2754 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);
2755 /* portlist is release at port_disconnect_release, thanx Paul */
2756 port_disconnect_release(portlist, message_type, param);
2759 /* PORT sends a TIMEOUT message */
2760 case MESSAGE_TIMEOUT:
2761 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);
2762 port_timeout(portlist, message_type, param);
2763 break; /* release */
2765 /* PORT sends a NOTIFY message */
2766 case MESSAGE_NOTIFY:
2767 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);
2768 port_notify(portlist, message_type, param);
2771 /* PORT sends a SUSPEND message */
2772 case MESSAGE_SUSPEND:
2773 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);
2774 port_suspend(portlist, message_type, param);
2775 break; /* suspend */
2777 /* PORT sends a RESUME message */
2778 case MESSAGE_RESUME:
2779 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);
2780 port_resume(portlist, message_type, param);
2784 kann nach dem test gelöscht werden, da eine direkte funktion im join und im mISDN zum austausch der message existiert
2785 /* port assigns bchannel */
2786 case MESSAGE_BCHANNEL: /* bchannel assignment messafe */
2787 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);
2788 /* only one port is expected to be connected to bchannel */
2789 message = message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2790 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_IN);
2796 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);
2799 /* Note: this endpoint may be destroyed, so we MUST return */
2803 /* messages from join
2805 /* join MESSAGE_CRYPT */
2806 void EndpointAppPBX::join_crypt(struct port_list *portlist, int message_type, union parameter *param)
2808 switch(param->crypt.type)
2810 /* message from remote port to "crypt manager" */
2811 case CU_ACTK_REQ: /* activate key-exchange */
2812 case CU_ACTS_REQ: /* activate shared key */
2813 case CU_DACT_REQ: /* deactivate */
2814 case CU_INFO_REQ: /* request last info message */
2815 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2818 /* message from "crypt manager" to user */
2819 case CU_ACTK_CONF: /* key-echange done */
2820 case CU_ACTS_CONF: /* shared key done */
2821 case CU_DACT_CONF: /* deactivated */
2822 case CU_DACT_IND: /* deactivated */
2823 case CU_ERROR_IND: /* receive error message */
2824 case CU_INFO_IND: /* receive info message */
2825 case CU_INFO_CONF: /* receive info message */
2826 encrypt_result(param->crypt.type, (char *)param->crypt.data);
2830 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);
2834 /* join MESSAGE_INFORMATION */
2835 void EndpointAppPBX::join_information(struct port_list *portlist, int message_type, union parameter *param)
2837 struct lcr_msg *message;
2843 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2844 memcpy(&message->param.information, ¶m->information, sizeof(struct dialing_info));
2845 message_put(message);
2846 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2847 portlist = portlist->next;
2851 /* join MESSAGE_FACILITY */
2852 void EndpointAppPBX::join_facility(struct port_list *portlist, int message_type, union parameter *param)
2854 struct lcr_msg *message;
2856 if (!e_ext.facility && e_ext.number[0])
2863 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_FACILITY);
2864 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2865 message_put(message);
2866 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2867 portlist = portlist->next;
2871 /* join MESSAGE_MORE */
2872 void EndpointAppPBX::join_overlap(struct port_list *portlist, int message_type, union parameter *param)
2874 struct lcr_msg *message;
2876 new_state(EPOINT_STATE_IN_OVERLAP);
2879 if (e_join_pattern && e_ext.own_setup)
2881 /* disconnect audio */
2882 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2883 message->param.audiopath = 0;
2884 message_put(message);
2886 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
2888 if (e_dialinginfo.id[0])
2889 set_tone(portlist, "dialing");
2891 set_tone(portlist, "dialtone");
2894 if (e_dialinginfo.id[0])
2896 set_tone(portlist, "dialing");
2899 if (e_ext.number[0])
2900 set_tone(portlist, "dialpbx");
2902 set_tone(portlist, "dialtone");
2906 /* join MESSAGE_PROCEEDING */
2907 void EndpointAppPBX::join_proceeding(struct port_list *portlist, int message_type, union parameter *param)
2909 struct lcr_msg *message;
2911 new_state(EPOINT_STATE_IN_PROCEEDING);
2913 /* own proceeding tone */
2916 /* connect / disconnect audio */
2917 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2918 if (e_ext.own_proceeding)
2919 message->param.audiopath = 0;
2921 message->param.audiopath = 1;
2922 message_put(message);
2924 // UCPY(e_join_tone, "proceeding");
2927 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
2928 message_put(message);
2929 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2931 set_tone(portlist, "proceeding");
2934 /* join MESSAGE_ALERTING */
2935 void EndpointAppPBX::join_alerting(struct port_list *portlist, int message_type, union parameter *param)
2937 struct lcr_msg *message;
2939 new_state(EPOINT_STATE_IN_ALERTING);
2941 /* own alerting tone */
2944 /* connect / disconnect audio */
2945 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2946 if (e_ext.own_alerting)
2947 message->param.audiopath = 0;
2949 message->param.audiopath = 1;
2950 message_put(message);
2954 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
2955 message_put(message);
2956 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2958 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
2960 set_tone(portlist, "ringing");
2963 if (e_ext.number[0])
2964 set_tone(portlist, "ringpbx");
2966 set_tone(portlist, "ringing");
2969 /* join MESSAGE_CONNECT */
2970 void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type, union parameter *param)
2972 struct lcr_msg *message;
2974 new_state(EPOINT_STATE_CONNECT);
2975 // UCPY(e_join_tone, "");
2977 if (e_ext.number[0])
2978 e_dtmf = 1; /* allow dtmf */
2981 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_callerinfo));
2984 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
2985 memcpy(&message->param, param, sizeof(union parameter));
2987 /* screen clip if prefix is required */
2988 if (e_ext.number[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0])
2990 SCPY(message->param.connectinfo.id, e_ext.clip_prefix);
2991 SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype, options.national, options.international));
2992 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2995 /* use internal caller id */
2996 if (e_ext.number[0] && e_connectinfo.extension[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
2998 SCPY(message->param.connectinfo.id, e_connectinfo.extension);
2999 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
3002 /* handle restricted caller ids */
3003 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);
3004 /* display callerid if desired for extension */
3005 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));
3007 /* use conp, if enabld */
3008 // if (!e_ext.centrex)
3009 // message->param.connectinfo.name[0] = '\0';
3012 message_put(message);
3013 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3015 set_tone(portlist, NULL);
3017 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3018 message->param.audiopath = 1;
3019 message_put(message);
3023 /* join MESSAGE_DISCONNECT MESSAGE_RELEASE */
3024 void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *param)
3027 struct lcr_msg *message;
3028 struct port_list *portlist = NULL;
3031 /* be sure that we are active */
3033 e_tx_state = NOTIFY_STATE_ACTIVE;
3035 /* we are powerdialing, if e_powerdialing is set and limit is not exceeded if given */
3036 if (e_powerdialing && ((e_powercount+1)<e_powerlimit || e_powerlimit<1))
3038 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
3040 /* set time for power dialing */
3041 e_powerdialing = now_d + e_powerdelay; /* set redial in the future */
3044 /* set redial tone */
3045 if (ea_endpoint->ep_portlist)
3049 set_tone(ea_endpoint->ep_portlist, "redial");
3050 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);
3051 /* send proceeding when powerdialing and still setup (avoid dialing timeout) */
3052 if (e_state==EPOINT_STATE_IN_OVERLAP)
3054 new_state(EPOINT_STATE_IN_PROCEEDING);
3055 if (ea_endpoint->ep_portlist)
3057 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3058 message_put(message);
3059 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3061 /* caused the error, that the first knock sound was not there */
3062 /* set_tone(portlist, "proceeding"); */
3064 /* send display of powerdialing */
3065 if (e_ext.display_dialing)
3067 portlist = ea_endpoint->ep_portlist;
3070 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3072 SPRINT(message->param.notifyinfo.display, "Retry %d of %d", e_powercount, e_powerlimit);
3074 SPRINT(message->param.notifyinfo.display, "Retry %d", e_powercount);
3075 message_put(message);
3076 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3077 portlist = portlist->next;
3086 if ((e_state!=EPOINT_STATE_CONNECT
3087 && e_state!=EPOINT_STATE_OUT_DISCONNECT
3088 && e_state!=EPOINT_STATE_IN_OVERLAP
3089 && e_state!=EPOINT_STATE_IN_PROCEEDING
3090 && e_state!=EPOINT_STATE_IN_ALERTING)
3091 || !ea_endpoint->ep_portlist) /* or no port */
3093 process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
3094 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause); /* RELEASE_TYPE, join, port */
3095 return; /* must exit here */
3100 e_join_cause = param->disconnectinfo.cause;
3101 e_join_location = param->disconnectinfo.location;
3104 /* on release we need the audio again! */
3105 if (message_type == MESSAGE_RELEASE)
3108 ea_endpoint->ep_join_id = 0;
3110 /* disconnect and select tone */
3111 new_state(EPOINT_STATE_OUT_DISCONNECT);
3112 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
3113 /* if own_cause, we must release the join */
3114 if (e_ext.own_cause /* own cause */
3115 || !e_join_pattern) /* no patterns */
3117 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);
3118 if (message_type != MESSAGE_RELEASE)
3119 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
3121 } else /* else we enable audio */
3123 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3124 message->param.audiopath = 1;
3125 message_put(message);
3127 /* send disconnect message */
3128 SCPY(e_tone, cause);
3129 portlist = ea_endpoint->ep_portlist;
3132 set_tone(portlist, cause);
3133 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
3134 portlist = portlist->next;
3138 /* join MESSAGE_SETUP */
3139 void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, union parameter *param)
3141 struct lcr_msg *message;
3142 // struct interface *interface;
3144 /* if we already in setup state, we just update the dialing with new digits */
3145 if (e_state == EPOINT_STATE_OUT_SETUP
3146 || e_state == EPOINT_STATE_OUT_OVERLAP)
3148 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we are in setup state, so we do overlap dialing.\n", ea_endpoint->ep_serial);
3149 /* if digits changed, what we have already dialed */
3150 if (!!strncmp(e_dialinginfo.id,param->setup.dialinginfo.id,strlen(e_dialinginfo.id)))
3152 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);
3153 /* release all ports */
3154 while((portlist = ea_endpoint->ep_portlist))
3156 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
3157 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
3158 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3159 message_put(message);
3160 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3161 ea_endpoint->free_portlist(portlist);
3164 /* disconnect audio */
3165 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3166 message->param.audiopath = 0;
3167 message_put(message);
3169 /* get dialing info */
3170 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3171 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3172 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3173 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3174 new_state(EPOINT_STATE_OUT_OVERLAP);
3177 e_redial = now_d + 1; /* set redial one second in the future */
3180 /* if we have a pending redial, so we just adjust the dialing number */
3183 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);
3184 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3187 if (!ea_endpoint->ep_portlist)
3189 PERROR("ERROR: overlap dialing to a NULL port relation\n");
3191 if (ea_endpoint->ep_portlist->next)
3193 PERROR("ERROR: overlap dialing to a port_list port relation\n");
3195 if (e_state == EPOINT_STATE_OUT_SETUP)
3198 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);
3199 SCAT(e_dialing_queue, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3203 /* get what we have not dialed yet */
3204 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));
3205 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
3206 SCPY(message->param.information.id, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3207 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
3208 message_put(message);
3209 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3211 /* always store what we have dialed or queued */
3212 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3216 if (e_state != EPOINT_STATE_IDLE)
3218 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
3221 /* if an internal extension is dialed, copy that number */
3222 if (param->setup.dialinginfo.itype==INFO_ITYPE_ISDN_EXTENSION || param->setup.dialinginfo.itype==INFO_ITYPE_VBOX)
3223 SCPY(e_ext.number, param->setup.dialinginfo.id);
3224 /* if an internal extension is dialed, get extension's info about caller */
3225 if (e_ext.number[0])
3227 if (!read_extension(&e_ext, e_ext.number))
3229 e_ext.number[0] = '\0';
3230 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the called terminal='%s' is not found in directory tree!\n", ea_endpoint->ep_serial, e_ext.number);
3234 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3235 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3236 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3237 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3239 /* process (voice over) data calls */
3240 if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO)
3242 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) handling data call as audio call: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
3243 memset(&e_capainfo, 0, sizeof(e_capainfo));
3244 e_capainfo.bearer_capa = INFO_BC_AUDIO;
3245 e_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
3246 e_capainfo.bearer_info1 = (options.law=='u')?INFO_INFO1_ULAW:INFO_INFO1_ALAW;
3249 new_state(EPOINT_STATE_OUT_SETUP);
3250 /* call special setup routine */
3254 /* join MESSAGE_mISDNSIGNAL */
3255 void EndpointAppPBX::join_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param)
3257 struct lcr_msg *message;
3261 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
3262 memcpy(&message->param, param, sizeof(union parameter));
3263 message_put(message);
3264 portlist = portlist->next;
3268 /* join MESSAGE_NOTIFY */
3269 void EndpointAppPBX::join_notify(struct port_list *portlist, int message_type, union parameter *param)
3271 struct lcr_msg *message;
3274 if (param->notifyinfo.notify)
3276 new_state = track_notify(e_tx_state, param->notifyinfo.notify);
3277 // /* if notification was generated locally, we turn hold music on/off */
3278 // if (param->notifyinfo.local)
3279 // 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)
3284 if (new_state!=NOTIFY_STATE_HOLD && new_state!=NOTIFY_STATE_SUSPEND)
3286 if (!strcmp(e_tone, "hold")) // don't interrupt other tones
3290 set_tone(portlist, "");
3291 portlist = portlist->next;
3294 portlist = ea_endpoint->ep_portlist;
3299 if (new_state==NOTIFY_STATE_HOLD || new_state==NOTIFY_STATE_SUSPEND)
3303 set_tone(portlist, "hold");
3304 portlist = portlist->next;
3306 portlist = ea_endpoint->ep_portlist;
3311 /* save new state */
3312 e_tx_state = new_state;
3315 /* notify port(s) about it */
3318 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3319 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
3320 /* handle restricted caller ids */
3321 apply_callerid_restriction(&e_ext, message->param.notifyinfo.id, &message->param.notifyinfo.ntype, &message->param.notifyinfo.present, 0, message->param.notifyinfo.extension, NULL);
3322 /* display callerid if desired for extension */
3323 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));
3324 message_put(message);
3325 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3326 portlist = portlist->next;
3330 /* JOIN sends messages to the endpoint
3332 void EndpointAppPBX::ea_message_join(unsigned int join_id, int message_type, union parameter *param)
3334 struct port_list *portlist;
3335 struct lcr_msg *message;
3339 PERROR("EPOINT(%d) error: JOIN == NULL.\n", ea_endpoint->ep_serial);
3343 portlist = ea_endpoint->ep_portlist;
3345 /* send MESSAGE_DATA to port */
3346 if (message_type == MESSAGE_DATA)
3348 if (join_id == ea_endpoint->ep_join_id) // still linked with JOIN
3350 /* skip if no port relation */
3353 /* skip if more than one port relation */
3356 /* forward audio data to port */
3357 message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3362 // 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);
3363 switch(message_type)
3365 /* JOIN SENDS TONE message */
3367 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);
3368 set_tone(portlist, param->tone.name);
3371 /* JOIN SENDS CRYPT message */
3373 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);
3374 join_crypt(portlist, message_type, param);
3377 /* JOIN sends INFORMATION message */
3378 case MESSAGE_INFORMATION:
3379 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);
3380 join_information(portlist, message_type, param);
3383 /* JOIN sends FACILITY message */
3384 case MESSAGE_FACILITY:
3385 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);
3386 join_facility(portlist, message_type, param);
3389 /* JOIN sends OVERLAP message */
3390 case MESSAGE_OVERLAP:
3391 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);
3392 if (e_state!=EPOINT_STATE_IN_SETUP
3393 && e_state!=EPOINT_STATE_IN_OVERLAP)
3395 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3398 join_overlap(portlist, message_type, param);
3401 /* JOIN sends PROCEEDING message */
3402 case MESSAGE_PROCEEDING:
3403 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);
3404 if(e_state!=EPOINT_STATE_IN_OVERLAP)
3406 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3409 join_proceeding(portlist, message_type, param);
3412 /* JOIN sends ALERTING message */
3413 case MESSAGE_ALERTING:
3414 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);
3415 if (e_state!=EPOINT_STATE_IN_OVERLAP
3416 && e_state!=EPOINT_STATE_IN_PROCEEDING)
3418 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state.\n", ea_endpoint->ep_serial);
3421 join_alerting(portlist, message_type, param);
3424 /* JOIN sends CONNECT message */
3425 case MESSAGE_CONNECT:
3426 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);
3427 if (e_state!=EPOINT_STATE_IN_OVERLAP
3428 && e_state!=EPOINT_STATE_IN_PROCEEDING
3429 && e_state!=EPOINT_STATE_IN_ALERTING)
3431 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
3434 join_connect(portlist, message_type, param);
3437 /* JOIN sends DISCONNECT/RELEASE message */
3438 case MESSAGE_DISCONNECT: /* JOIN disconnect */
3439 case MESSAGE_RELEASE: /* JOIN releases */
3440 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);
3441 join_disconnect_release(message_type, param);
3444 /* JOIN sends SETUP message */
3446 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);
3447 join_setup(portlist, message_type, param);
3450 /* JOIN sends special mISDNSIGNAL message */
3451 case MESSAGE_mISDNSIGNAL: /* isdn message to port */
3452 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);
3453 join_mISDNsignal(portlist, message_type, param);
3457 kann nach dem test gelöscht werden, da eine direkte funktion im join und im mISDN zum austausch der message existiert
3458 /* JOIN requests bchannel */
3459 case MESSAGE_BCHANNEL: /* indicates the need of own bchannel access */
3460 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);
3461 /* only one port is expected to be connected to bchannel */
3468 set_tone(portlist, NULL);
3469 message = message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3470 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3474 /* JOIN has pattern available */
3475 case MESSAGE_PATTERN: /* indicating pattern available */
3476 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);
3477 if (!e_join_pattern)
3479 PDEBUG(DEBUG_EPOINT, "-> pattern becomes available\n");
3484 set_tone(portlist, NULL);
3485 portlist = portlist->next;
3487 /* connect our audio tx and rx (blueboxing should be possibe before connect :)*/
3488 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3489 message->param.audiopath = 1;
3490 message_put(message);
3494 /* JOIN has no pattern available */
3495 case MESSAGE_NOPATTERN: /* indicating no pattern available */
3496 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);
3499 PDEBUG(DEBUG_EPOINT, "-> pattern becomes unavailable\n");
3501 /* disconnect our audio tx and rx */
3502 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3503 message->param.audiopath = 0;
3504 message_put(message);
3509 /* JOIN (dunno at the moment) */
3510 case MESSAGE_REMOTE_AUDIO:
3511 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);
3512 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3513 message->param.audiopath = param->channel;
3514 message_put(message);
3518 /* JOIN sends a notify message */
3519 case MESSAGE_NOTIFY:
3520 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);
3521 join_notify(portlist, message_type, param);
3524 /* JOIN wants keypad / dtml */
3525 case MESSAGE_ENABLEKEYPAD:
3526 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);
3529 trace_header("ENABLE KEYPAD", DIRECTION_NONE);
3534 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);
3539 /* pick_join will connect the first incoming call found. the endpoint
3540 * will receivce a MESSAGE_CONNECT.
3542 int match_list(char *list, char *item)
3544 char *end, *next = NULL;
3546 /* no list make matching */
3552 /* eliminate white spaces */
3553 while (*list <= ' ')
3560 /* if end of list is reached, we return */
3561 if (list[0] == '\0')
3563 /* if we have more than one entry (left) */
3564 if ((end = strchr(list, ',')))
3567 next = end = strchr(list, '\0');
3568 while (*(end-1) <= ' ')
3570 /* if string part matches item */
3571 if (!strncmp(list, item, end-list))
3577 void EndpointAppPBX::pick_join(char *extensions)
3579 struct lcr_msg *message;
3580 struct port_list *portlist;
3582 class EndpointAppPBX *eapp, *found;
3584 class JoinPBX *joinpbx;
3585 struct join_relation *relation;
3588 /* find an endpoint that is ringing internally or vbox with higher priority */
3591 eapp = apppbx_first;
3594 if (eapp!=this && ea_endpoint->ep_portlist)
3596 portlist = eapp->ea_endpoint->ep_portlist;
3599 if ((port = find_port_id(portlist->port_id)))
3601 if (port->p_type == PORT_TYPE_VBOX_OUT)
3603 if (match_list(extensions, eapp->e_ext.number))
3610 if ((port->p_type==PORT_TYPE_DSS1_NT_OUT || port->p_type==PORT_TYPE_DSS1_TE_OUT)
3611 && port->p_state==PORT_STATE_OUT_ALERTING)
3612 if (match_list(extensions, eapp->e_ext.number))
3617 portlist = portlist->next;
3625 /* if no endpoint found */
3628 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);
3630 set_tone(ea_endpoint->ep_portlist, "cause_10");
3631 message_disconnect_port(ea_endpoint->ep_portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
3632 new_state(EPOINT_STATE_OUT_DISCONNECT);
3637 if (ea_endpoint->ep_join_id)
3639 PERROR("EPOINT(%d) we already have a join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3642 if (!eapp->ea_endpoint->ep_join_id)
3644 PERROR("EPOINT(%d) ringing endpoint has no join.\n", ea_endpoint->ep_serial);
3647 join = find_join_id(eapp->ea_endpoint->ep_join_id);
3650 PERROR("EPOINT(%d) ringing endpoint's join not found.\n", ea_endpoint->ep_serial);
3653 if (join->j_type != JOIN_TYPE_PBX)
3655 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ringing endpoint's join is not a PBX join, so we must reject.\n", ea_endpoint->ep_serial);
3658 joinpbx = (class JoinPBX *)join;
3659 relation = joinpbx->j_relation;
3662 PERROR("EPOINT(%d) ringing endpoint's join has no relation. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3665 while (relation->epoint_id != eapp->ea_endpoint->ep_serial)
3667 relation = relation->next;
3670 PERROR("EPOINT(%d) ringing endpoint's join has no relation to that join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3675 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found ringing endpoint: %d.\n", ea_endpoint->ep_serial, eapp->ea_endpoint->ep_serial);
3677 if (options.deb & DEBUG_EPOINT)
3679 class Join *debug_c = join_first;
3680 class Endpoint *debug_e = epoint_first;
3681 class Port *debug_p = port_first;
3683 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(before)");
3685 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3688 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3689 debug_c = debug_c->next;
3691 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3694 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3695 debug_e = debug_e->next;
3697 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3700 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld (active)\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3701 debug_p = debug_p->next;
3706 ea_endpoint->ep_join_id = eapp->ea_endpoint->ep_join_id; /* we get the join */
3707 relation->epoint_id = ea_endpoint->ep_serial; /* the join gets us */
3708 eapp->ea_endpoint->ep_join_id = 0; /* the ringing endpoint will get disconnected */
3710 /* connnecting our endpoint */
3711 new_state(EPOINT_STATE_CONNECT);
3712 if (e_ext.number[0])
3714 set_tone(ea_endpoint->ep_portlist, NULL);
3716 /* now we send a release to the ringing endpoint */
3717 message = message_create(ea_endpoint->ep_join_id, eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3718 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
3719 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3720 message_put(message);
3722 /* we send a connect to the join with our caller id */
3723 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CONNECT);
3724 SCPY(message->param.connectinfo.id, e_callerinfo.id);
3725 message->param.connectinfo.present = e_callerinfo.present;
3726 message->param.connectinfo.screen = e_callerinfo.screen;
3727 message->param.connectinfo.itype = e_callerinfo.itype;
3728 message->param.connectinfo.ntype = e_callerinfo.ntype;
3729 message_put(message);
3731 /* we send a connect to our port with the remote callerid */
3732 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3733 SCPY(message->param.connectinfo.id, eapp->e_callerinfo.id);
3734 message->param.connectinfo.present = eapp->e_callerinfo.present;
3735 message->param.connectinfo.screen = eapp->e_callerinfo.screen;
3736 message->param.connectinfo.itype = eapp->e_callerinfo.itype;
3737 message->param.connectinfo.ntype = eapp->e_callerinfo.ntype;
3738 /* handle restricted caller ids */
3739 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);
3740 /* display callerid if desired for extension */
3741 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));
3742 message_put(message);
3744 /* we send a connect to the audio path (not for vbox) */
3745 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3746 message->param.audiopath = 1;
3747 message_put(message);
3749 /* beeing paranoid, we make call update */
3750 joinpbx->j_updatebridge = 1;
3752 if (options.deb & DEBUG_EPOINT)
3754 class Join *debug_c = join_first;
3755 class Endpoint *debug_e = epoint_first;
3756 class Port *debug_p = port_first;
3758 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(after)");
3760 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3763 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3764 debug_c = debug_c->next;
3766 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3769 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3770 debug_e = debug_e->next;
3772 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3775 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3776 debug_p = debug_p->next;
3782 /* join calls (look for a join that is on hold (same isdn interface/terminal))
3784 void EndpointAppPBX::join_join(void)
3786 struct lcr_msg *message;
3787 struct join_relation *our_relation, *other_relation;
3788 struct join_relation **our_relation_pointer, **other_relation_pointer;
3789 class Join *our_join, *other_join;
3790 class JoinPBX *our_joinpbx, *other_joinpbx;
3791 class EndpointAppPBX *other_eapp; class Endpoint *temp_epoint;
3792 class Port *our_port, *other_port;
3793 class Pdss1 *our_pdss1, *other_pdss1;
3795 /* are we a candidate to join a join */
3796 our_join = find_join_id(ea_endpoint->ep_join_id);
3799 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3802 if (our_join->j_type != JOIN_TYPE_PBX)
3804 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: join is not a pbx join.\n", ea_endpoint->ep_serial);
3807 our_joinpbx = (class JoinPBX *)our_join;
3808 if (!ea_endpoint->ep_portlist)
3810 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
3813 if (!e_ext.number[0])
3815 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
3818 our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
3821 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
3824 if ((our_port->p_type&PORT_CLASS_mISDN_MASK) != PORT_CLASS_mISDN_DSS1)
3826 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not isdn.\n", ea_endpoint->ep_serial);
3829 our_pdss1 = (class Pdss1 *)our_port;
3831 /* find an endpoint that is on hold and has the same mISDNport that we are on */
3832 other_eapp = apppbx_first;
3835 if (other_eapp == this)
3837 other_eapp = other_eapp->next;
3840 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);
3841 if (other_eapp->e_ext.number[0] /* has terminal */
3842 && other_eapp->ea_endpoint->ep_portlist /* has port */
3843 && other_eapp->ea_endpoint->ep_join_id) /* has join */
3845 other_port = find_port_id(other_eapp->ea_endpoint->ep_portlist->port_id);
3846 if (other_port) /* port still exists */
3848 if (other_port->p_type==PORT_TYPE_DSS1_NT_OUT
3849 || other_port->p_type==PORT_TYPE_DSS1_NT_IN) /* port is isdn nt-mode */
3851 other_pdss1 = (class Pdss1 *)other_port;
3852 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);
3853 if (other_pdss1->p_m_hold /* port is on hold */
3854 && other_pdss1->p_m_mISDNport == our_pdss1->p_m_mISDNport /* same isdn interface */
3855 && other_pdss1->p_m_d_ces == our_pdss1->p_m_d_ces) /* same tei+sapi */
3859 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of other type!\n", ea_endpoint->ep_serial);
3863 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port doesn't exist enymore.\n", ea_endpoint->ep_serial);
3866 other_eapp = other_eapp->next;
3870 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn interface with port on hold.\n", ea_endpoint->ep_serial);
3873 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port on hold found.\n", ea_endpoint->ep_serial);
3875 /* if we have the same join */
3876 if (other_eapp->ea_endpoint->ep_join_id == ea_endpoint->ep_join_id)
3878 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we an the other have the same join.\n", ea_endpoint->ep_serial);
3881 other_join = find_join_id(other_eapp->ea_endpoint->ep_join_id);
3884 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3887 if (other_join->j_type != JOIN_TYPE_PBX)
3889 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join is not a pbx join.\n", ea_endpoint->ep_serial);
3892 other_joinpbx = (class JoinPBX *)other_join;
3893 if (our_joinpbx->j_partyline && other_joinpbx->j_partyline)
3895 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both joins are partylines.\n", ea_endpoint->ep_serial);
3899 /* remove relation to endpoint for join on hold */
3900 other_relation = other_joinpbx->j_relation;
3901 other_relation_pointer = &other_joinpbx->j_relation;
3902 while(other_relation)
3904 if (other_relation->epoint_id == other_eapp->ea_endpoint->ep_serial)
3906 /* detach other endpoint on hold */
3907 *other_relation_pointer = other_relation->next;
3908 FREE(other_relation, sizeof(struct join_relation));
3910 other_relation = *other_relation_pointer;
3911 other_eapp->ea_endpoint->ep_join_id = 0;
3915 /* change join/hold pointer of endpoint to the new join */
3916 temp_epoint = find_epoint_id(other_relation->epoint_id);
3919 if (temp_epoint->ep_join_id == other_join->j_serial)
3920 temp_epoint->ep_join_id = our_join->j_serial;
3923 other_relation_pointer = &other_relation->next;
3924 other_relation = other_relation->next;
3926 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint on hold removed, other enpoints on join relinked (to our join).\n", ea_endpoint->ep_serial);
3928 /* join call relations */
3929 our_relation = our_joinpbx->j_relation;
3930 our_relation_pointer = &our_joinpbx->j_relation;
3933 our_relation_pointer = &our_relation->next;
3934 our_relation = our_relation->next;
3936 *our_relation_pointer = other_joinpbx->j_relation;
3937 other_joinpbx->j_relation = NULL;
3938 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) relations joined.\n", ea_endpoint->ep_serial);
3940 /* release endpoint on hold */
3941 message = message_create(other_joinpbx->j_serial, other_eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3942 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */
3943 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3944 message_put(message);
3946 /* if we are not a partyline, we get partyline state from other join */
3947 our_joinpbx->j_partyline += other_joinpbx->j_partyline;
3949 /* remove empty join */
3951 PDEBUG(DEBUG_EPOINT, "EPOINT(%d)d-join completely removed!\n");
3953 /* mixer must update */
3954 our_joinpbx->j_updatebridge = 1; /* update mixer flag */
3956 /* we send a retrieve to that endpoint */
3957 // mixer will update the hold-state of the join and send it to the endpoints is changes
3961 /* check if we have an external call
3962 * this is used to check for encryption ability
3964 int EndpointAppPBX::check_external(char **errstr, class Port **port)
3966 struct join_relation *relation;
3968 class JoinPBX *joinpbx;
3969 class Endpoint *epoint;
3971 /* some paranoia check */
3972 if (!ea_endpoint->ep_portlist)
3974 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we have no port.\n", ea_endpoint->ep_serial);
3975 *errstr = "No Call";
3978 if (!e_ext.number[0])
3980 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we are not internal extension.\n", ea_endpoint->ep_serial);
3981 *errstr = "No Call";
3985 /* check if we have a join with 2 parties */
3986 join = find_join_id(ea_endpoint->ep_join_id);
3989 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have currently no join.\n", ea_endpoint->ep_serial);
3990 *errstr = "No Call";
3993 if (join->j_type != JOIN_TYPE_PBX)
3995 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join is not a pbx join.\n", ea_endpoint->ep_serial);
3996 *errstr = "No PBX Call";
3999 joinpbx = (class JoinPBX *)join;
4000 relation = joinpbx->j_relation;
4003 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no relation.\n", ea_endpoint->ep_serial);
4004 *errstr = "No Call";
4007 if (!relation->next)
4009 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd relation.\n", ea_endpoint->ep_serial);
4010 *errstr = "No Call";
4013 if (relation->next->next)
4015 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has more than two relations.\n", ea_endpoint->ep_serial);
4016 *errstr = "Err: Conference";
4019 if (relation->epoint_id == ea_endpoint->ep_serial)
4021 relation = relation->next;
4022 if (relation->epoint_id == ea_endpoint->ep_serial)
4024 PERROR("EPOINT(%d) SOFTWARE ERROR: both join relations are related to our endpoint.\n", ea_endpoint->ep_serial);
4025 *errstr = "Software Error";
4030 /* check remote port for external call */
4031 epoint = find_epoint_id(relation->epoint_id);
4034 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd endpoint.\n", ea_endpoint->ep_serial);
4035 *errstr = "No Call";
4038 if (!epoint->ep_portlist)
4040 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not port.\n", ea_endpoint->ep_serial);
4041 *errstr = "No Call";
4044 *port = find_port_id(epoint->ep_portlist->port_id);
4047 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has an none existing port.\n", ea_endpoint->ep_serial);
4048 *errstr = "No Call";
4051 if (((*port)->p_type&PORT_CLASS_mISDN_MASK)!=PORT_CLASS_mISDN_DSS1) /* port is not external isdn */
4053 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not an external port.\n", ea_endpoint->ep_serial);
4054 *errstr = "No Ext Call";
4057 if ((*port)->p_state != PORT_STATE_CONNECT)
4059 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint's port is not in connected state.\n", ea_endpoint->ep_serial);
4060 *errstr = "No Ext Connect";
4066 void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsigned int port_id, int dir)
4068 char *logtext = "unknown";
4071 switch(message_type)
4074 trace_header("SETUP", dir);
4075 if (dir == DIRECTION_OUT)
4076 add_trace("to", NULL, "CH(%lu)", port_id);
4077 if (dir == DIRECTION_IN)
4078 add_trace("from", NULL, "CH(%lu)", port_id);
4079 if (param->setup.callerinfo.extension[0])
4080 add_trace("extension", NULL, "%s", param->setup.callerinfo.extension);
4081 add_trace("caller id", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype, options.national, options.international));
4082 switch(param->setup.callerinfo.present)
4084 case INFO_PRESENT_RESTRICTED:
4085 add_trace("caller id", "present", "restricted");
4087 case INFO_PRESENT_ALLOWED:
4088 add_trace("caller id", "present", "allowed");
4091 add_trace("caller id", "present", "not available");
4093 if (param->setup.redirinfo.id[0])
4095 add_trace("redir'ing", "number", "%s", numberrize_callerinfo(param->setup.redirinfo.id, param->setup.redirinfo.ntype, options.national, options.international));
4096 switch(param->setup.redirinfo.present)
4098 case INFO_PRESENT_RESTRICTED:
4099 add_trace("redir'ing", "present", "restricted");
4101 case INFO_PRESENT_ALLOWED:
4102 add_trace("redir'ing", "present", "allowed");
4105 add_trace("redir'ing", "present", "not available");
4108 if (param->setup.dialinginfo.id[0])
4109 add_trace("dialing", NULL, "%s", param->setup.dialinginfo.id);
4110 if (param->setup.dialinginfo.display[0])
4111 add_trace("display", NULL, "%s", param->setup.dialinginfo.display);
4112 if (param->setup.dialinginfo.sending_complete)
4113 add_trace("complete", NULL, "true", param->setup.dialinginfo.sending_complete);
4117 case MESSAGE_OVERLAP:
4118 trace_header("SETUP ACKNOWLEDGE", dir);
4119 if (dir == DIRECTION_OUT)
4120 add_trace("to", NULL, "CH(%lu)", port_id);
4121 if (dir == DIRECTION_IN)
4122 add_trace("from", NULL, "CH(%lu)", port_id);
4126 case MESSAGE_PROCEEDING:
4127 trace_header("PROCEEDING", dir);
4128 if (dir == DIRECTION_OUT)
4129 add_trace("to", NULL, "CH(%lu)", port_id);
4130 if (dir == DIRECTION_IN)
4131 add_trace("from", NULL, "CH(%lu)", port_id);
4135 case MESSAGE_ALERTING:
4136 trace_header("ALERTING", dir);
4137 if (dir == DIRECTION_OUT)
4138 add_trace("to", NULL, "CH(%lu)", port_id);
4139 if (dir == DIRECTION_IN)
4140 add_trace("from", NULL, "CH(%lu)", port_id);
4144 case MESSAGE_CONNECT:
4145 trace_header("CONNECT", dir);
4146 if (dir == DIRECTION_OUT)
4147 add_trace("to", NULL, "CH(%lu)", port_id);
4148 if (dir == DIRECTION_IN)
4149 add_trace("from", NULL, "CH(%lu)", port_id);
4150 if (param->connectinfo.extension[0])
4151 add_trace("extension", NULL, "%s", param->connectinfo.extension);
4152 add_trace("connect id", "number", "%s", numberrize_callerinfo(param->connectinfo.id, param->connectinfo.ntype, options.national, options.international));
4153 switch(param->connectinfo.present)
4155 case INFO_PRESENT_RESTRICTED:
4156 add_trace("connect id", "present", "restricted");
4158 case INFO_PRESENT_ALLOWED:
4159 add_trace("connect id", "present", "allowed");
4162 add_trace("connect id", "present", "not available");
4164 if (param->connectinfo.display[0])
4165 add_trace("display", NULL, "%s", param->connectinfo.display);
4169 case MESSAGE_DISCONNECT:
4170 case MESSAGE_RELEASE:
4171 if (message_type == MESSAGE_DISCONNECT)
4172 trace_header("DISCONNECT", dir);
4174 trace_header("RELEASE", dir);
4175 if (dir == DIRECTION_OUT)
4176 add_trace("to", NULL, "CH(%lu)", port_id);
4177 if (dir == DIRECTION_IN)
4178 add_trace("from", NULL, "CH(%lu)", port_id);
4179 add_trace("cause", "value", "%d", param->disconnectinfo.cause);
4180 switch(param->disconnectinfo.location)
4183 add_trace("cause", "location", "0-User");
4185 case LOCATION_PRIVATE_LOCAL:
4186 add_trace("cause", "location", "1-Local-PBX");
4188 case LOCATION_PUBLIC_LOCAL:
4189 add_trace("cause", "location", "2-Local-Exchange");
4191 case LOCATION_TRANSIT:
4192 add_trace("cause", "location", "3-Transit");
4194 case LOCATION_PUBLIC_REMOTE:
4195 add_trace("cause", "location", "4-Remote-Exchange");
4197 case LOCATION_PRIVATE_REMOTE:
4198 add_trace("cause", "location", "5-Remote-PBX");
4200 case LOCATION_INTERNATIONAL:
4201 add_trace("cause", "location", "7-International-Exchange");
4203 case LOCATION_BEYOND:
4204 add_trace("cause", "location", "10-Beyond-Interworking");
4207 add_trace("cause", "location", "%d", param->disconnectinfo.location);
4209 if (param->disconnectinfo.display[0])
4210 add_trace("display", NULL, "%s", param->disconnectinfo.display);
4214 case MESSAGE_NOTIFY:
4215 switch(param->notifyinfo.notify)
4221 logtext = "USER_SUSPENDED";
4224 logtext = "BEARER_SERVICE_CHANGED";
4227 logtext = "USER_RESUMED";
4230 logtext = "CONFERENCE_ESTABLISHED";
4233 logtext = "CONFERENCE_DISCONNECTED";
4236 logtext = "OTHER_PARTY_ADDED";
4239 logtext = "ISOLATED";
4242 logtext = "REATTACHED";
4245 logtext = "OTHER_PARTY_ISOLATED";
4248 logtext = "OTHER_PARTY_REATTACHED";
4251 logtext = "OTHER_PARTY_SPLIT";
4254 logtext = "OTHER_PARTY_DISCONNECTED";
4257 logtext = "CONFERENCE_FLOATING";
4260 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
4263 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
4266 logtext = "CALL_IS_A_WAITING_CALL";
4269 logtext = "DIVERSION_ACTIVATED";
4272 logtext = "RESERVED_CT_1";
4275 logtext = "RESERVED_CT_2";
4278 logtext = "REVERSE_CHARGING";
4281 logtext = "REMOTE_HOLD";
4284 logtext = "REMOTE_RETRIEVAL";
4287 logtext = "CALL_IS_DIVERTING";
4290 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
4294 trace_header("NOTIFY", dir);
4295 if (dir == DIRECTION_OUT)
4296 add_trace("to", NULL, "CH(%lu)", port_id);
4297 if (dir == DIRECTION_IN)
4298 add_trace("from", NULL, "CH(%lu)", port_id);
4299 if (param->notifyinfo.notify)
4300 add_trace("indicator", NULL, "%s", logtext);
4301 if (param->notifyinfo.id[0])
4303 add_trace("redir'on", "number", "%s", numberrize_callerinfo(param->notifyinfo.id, param->notifyinfo.ntype, options.national, options.international));
4304 switch(param->notifyinfo.present)
4306 case INFO_PRESENT_RESTRICTED:
4307 add_trace("redir'on", "present", "restricted");
4309 case INFO_PRESENT_ALLOWED:
4310 add_trace("redir'on", "present", "allowed");
4313 add_trace("redir'on", "present", "not available");
4316 if (param->notifyinfo.display[0])
4317 add_trace("display", NULL, "%s", param->notifyinfo.display);
4321 case MESSAGE_INFORMATION:
4322 trace_header("INFORMATION", dir);
4323 if (dir == DIRECTION_OUT)
4324 add_trace("to", NULL, "CH(%lu)", port_id);
4325 if (dir == DIRECTION_IN)
4326 add_trace("from", NULL, "CH(%lu)", port_id);
4327 if (param->information.id[0])
4328 add_trace("dialing", NULL, "%s", param->information.id);
4329 if (param->information.display[0])
4330 add_trace("display", NULL, "%s", param->information.display);
4331 if (param->information.sending_complete)
4332 add_trace("complete", NULL, "true", param->information.sending_complete);
4336 case MESSAGE_FACILITY:
4337 trace_header("FACILITY", dir);
4338 if (dir == DIRECTION_OUT)
4339 add_trace("to", NULL, "CH(%lu)", port_id);
4340 if (dir == DIRECTION_IN)
4341 add_trace("from", NULL, "CH(%lu)", port_id);
4346 trace_header("TONE", dir);
4347 if (dir == DIRECTION_OUT)
4348 add_trace("to", NULL, "CH(%lu)", port_id);
4349 if (dir == DIRECTION_IN)
4350 add_trace("from", NULL, "CH(%lu)", port_id);
4351 if (param->tone.name[0])
4353 add_trace("directory", NULL, "%s", param->tone.dir[0]?param->tone.dir:"default");
4354 add_trace("name", NULL, "%s", param->tone.name);
4356 add_trace("off", NULL, NULL);
4360 case MESSAGE_SUSPEND:
4361 case MESSAGE_RESUME:
4362 if (message_type == MESSAGE_SUSPEND)
4363 trace_header("SUSPEND", dir);
4365 trace_header("RESUME", dir);
4366 if (dir == DIRECTION_OUT)
4367 add_trace("to", NULL, "CH(%lu)", port_id);
4368 if (dir == DIRECTION_IN)
4369 add_trace("from", NULL, "CH(%lu)", port_id);
4370 if (param->parkinfo.len)
4371 add_trace("length", NULL, "%d", param->parkinfo.len);
4376 case MESSAGE_BCHANNEL:
4377 trace_header("BCHANNEL", dir);
4378 switch(param->bchannel.type)
4380 case BCHANNEL_REQUEST:
4381 add_trace("type", NULL, "request");
4383 case BCHANNEL_ASSIGN:
4384 add_trace("type", NULL, "assign");
4386 case BCHANNEL_ASSIGN_ACK:
4387 add_trace("type", NULL, "assign_ack");
4389 case BCHANNEL_REMOVE:
4390 add_trace("type", NULL, "remove");
4392 case BCHANNEL_REMOVE_ACK:
4393 add_trace("type", NULL, "remove_ack");
4396 if (param->bchannel.addr)
4397 add_trace("address", NULL, "%x", param->bchannel.addr);
4403 PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message_type);
4407 void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cause, int location, char *display)
4409 struct lcr_msg *message;
4413 if (!portlist->port_id)
4416 if (!e_connectedmode)
4418 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT);
4419 message->param.disconnectinfo.cause = cause;
4420 message->param.disconnectinfo.location = location;
4422 SCPY(message->param.disconnectinfo.display, display);
4424 SCPY(message->param.disconnectinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4427 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
4429 SCPY(message->param.notifyinfo.display, display);
4431 SCPY(message->param.notifyinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4433 message_put(message);
4434 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);