1 /*****************************************************************************\
3 ** Linux Call Router **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
8 ** The EndpointAppPBX implements PBX4Linux **
10 \*****************************************************************************/
15 class EndpointAppPBX *apppbx_first = NULL;
18 * EndpointAppPBX constructor
20 EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint, int origin) : EndpointApp(epoint, origin)
22 class EndpointAppPBX **apppointer;
24 /* add application to chain */
26 apppointer = &apppbx_first;
28 apppointer = &((*apppointer)->next);
32 memset(&e_ext, 0, sizeof(struct extension));
33 // *************** NOTE: also change value in read_extension() **************
34 e_ext.rights = 4; /* international */
35 e_ext.rx_gain = e_ext.tx_gain = 0;
36 e_state = EPOINT_STATE_IDLE;
37 e_ext.number[0] = '\0';
38 e_extension_interface[0] = '\0';
39 memset(&e_callerinfo, 0, sizeof(struct caller_info));
40 memset(&e_dialinginfo, 0, sizeof(struct dialing_info));
41 memset(&e_connectinfo, 0, sizeof(struct connect_info));
42 memset(&e_redirinfo, 0, sizeof(struct redir_info));
43 memset(&e_capainfo, 0, sizeof(struct capa_info));
46 e_ruleset = ruleset_main;
48 e_rule = e_ruleset->rule_first;
53 e_match_to_action = NULL;
55 e_extdialing = e_dialinginfo.id;
59 // e_join_tone[0] = e_hold_tone[0] = '\0';
60 e_join_pattern /*= e_hold_pattern*/ = 0;
63 e_adminid = 0; // will be set, if call was initiated via admin socket
68 e_cbdialing[0] = '\0';
71 memset(&e_callbackinfo, 0, sizeof(struct caller_info));
79 e_password_timeout = 0;
80 e_multipoint_cause = 0;
81 e_multipoint_location = 0;
82 e_dialing_queue[0] = '\0';
84 e_crypt_state = CM_ST_NULL;
85 e_crypt_keyengine_busy = 0;
86 e_crypt_info[0] = '\0';
89 e_tx_state = NOTIFY_STATE_ACTIVE;
90 e_rx_state = NOTIFY_STATE_ACTIVE;
91 e_join_cause = e_join_location = 0;
92 /*********************************
93 *********************************
94 ********* ATTENTION *************
95 *********************************
96 *********************************/
97 /* if you add new values, that must be initialized, also check if they must
98 * be initialized when doing callback
104 * EpointAppPBX destructor
106 EndpointAppPBX::~EndpointAppPBX(void)
108 class EndpointAppPBX *temp, **tempp;
112 tempp = &apppbx_first;
122 FATAL("Endpoint not in endpoint's list.\n");
129 * trace header for application
131 void EndpointAppPBX::trace_header(const char *name, int direction)
135 char msgtext[sizeof(_trace.name)];
139 /* init trace with given values */
142 numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype, options.national, options.international),
146 ea_endpoint->ep_serial,
153 /* set new endpoint state
155 void EndpointAppPBX::new_state(int state)
158 if (e_state != state)
160 trace_header("NEW STATE", DIRECTION_NONE);
161 add_trace("state", "old", "%s", state_name[e_state]);
162 add_trace("state", "new", "%s", state_name[state]);
170 /* release join and port (as specified)
172 void EndpointAppPBX::release(int release, int joinlocation, int joincause, int portlocation, int portcause)
174 struct port_list *portlist;
175 struct lcr_msg *message;
178 /* message to test call */
179 admin_call_response(e_adminid, ADMIN_CALL_RELEASE, "", joincause, joinlocation, 0);
181 /* if a release is pending */
182 if (release==RELEASE_JOIN || release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY)
184 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): do pending release (joincause %d location %d)\n", ea_endpoint->ep_serial, joincause, joinlocation);
185 if (ea_endpoint->ep_join_id)
187 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_RELEASE);
188 message->param.disconnectinfo.cause = joincause;
189 message->param.disconnectinfo.location = joinlocation;
190 message_put(message);
191 ea_endpoint->ep_join_id = 0;
195 if (release != RELEASE_PORT_JOINONLY)
198 join_release(e_hold_id, ea_endpoint->ep_serial, 1, joinlocation, joincause);
203 if (release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY)
205 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release (portcause %d portlocation)\n", ea_endpoint->ep_serial, portcause, portlocation);
206 while((portlist = ea_endpoint->ep_portlist))
208 if (portlist->port_id)
210 SPRINT(cause, "cause_%02x", portcause);
211 set_tone(portlist, cause);
212 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
213 message->param.disconnectinfo.cause = portcause;
214 message->param.disconnectinfo.location = portlocation;
215 message_put(message);
216 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
218 ea_endpoint->free_portlist(portlist);
221 /* if callback is enabled, call back with the given caller id */
224 /* reset some stuff */
225 new_state(EPOINT_STATE_IDLE);
226 memset(&e_connectinfo, 0, sizeof(struct connect_info));
227 memset(&e_redirinfo, 0, sizeof(struct redir_info));
228 e_start = e_stop = 0;
229 e_ruleset = ruleset_main;
231 e_rule = e_ruleset->rule_first;
233 e_action_timeout = 0;
235 e_match_to_action = NULL;
237 e_extdialing = e_dialinginfo.id;
245 e_multipoint_cause = 0;
246 e_multipoint_location = 0;
247 e_dialing_queue[0] = '\0';
249 e_crypt_state = CM_ST_NULL;
250 e_crypt_keyengine_busy = 0;
251 e_crypt_info[0] = '\0';
255 e_tx_state = NOTIFY_STATE_ACTIVE;
256 e_rx_state = NOTIFY_STATE_ACTIVE;
257 e_join_cause = e_join_location = 0;
259 /* the caller info of the callback user */
260 memcpy(&e_callbackinfo, &e_callerinfo, sizeof(e_callbackinfo));
261 memset(&e_dialinginfo, 0, sizeof(e_dialinginfo));
262 /* create dialing by callerinfo */
263 if (e_ext.number[0] && e_extension_interface[0])
265 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to internal: %s interface %s\n", ea_endpoint->ep_serial, e_ext.number, e_extension_interface);
266 /* create callback to the current terminal */
267 SCPY(e_dialinginfo.id, e_ext.number);
268 SCPY(e_dialinginfo.interfaces, e_extension_interface);
269 e_dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
270 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
275 SCPY(e_dialinginfo.id, e_cbto);
278 /* numberrize caller id and use it to dial to the callback */
279 SCPY(e_dialinginfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype, options.national, options.international));
281 e_dialinginfo.itype = INFO_ITYPE_ISDN;
282 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
283 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to external: %s\n", ea_endpoint->ep_serial, e_dialinginfo.id);
288 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release of epoint itself.\n", ea_endpoint->ep_serial);
289 ea_endpoint->ep_use--; /* when e_lock is 0, the endpoint will be deleted */
295 /* cancel callerid if restricted, unless anon-ignore is enabled at extension or port is of type external (so called police gets caller id :)*/
296 void apply_callerid_restriction(struct extension *ext, char *id, int *ntype, int *present, int *screen, char *extension, char *name)
298 PDEBUG(DEBUG_EPOINT, "id='%s' ntype=%d present=%d screen=%d extension='%s' name='%s'\n", (id)?id:"NULL", (ntype)?*ntype:-1, (present)?*present:-1, (screen)?*screen:-1, (extension)?extension:"NULL", (name)?name:"NULL");
300 /* caller id is not restricted, so we do nothing */
301 if (*present != INFO_PRESENT_RESTRICTED)
304 /* only extensions are restricted */
308 /* if we enabled anonymouse ignore */
309 if (ext->anon_ignore)
312 /* else we remove the caller id */
316 *ntype = INFO_NTYPE_UNKNOWN;
318 // *screen = INFO_SCREEN_USER;
319 // maybe we should not make voip address anonymous
322 // maybe it's no fraud to present extension id
324 // extension[0] = '\0';
329 /* used display message to display callerid as available */
330 char *EndpointAppPBX::apply_callerid_display(const char *id, int itype, int ntype, int present, int screen, const char *extension, const char *name)
332 static char display[81];
335 const char *cid = numberrize_callerinfo(id, ntype, options.national, options.international);
337 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) id='%s' itype=%d ntype=%d present=%d screen=%d extension='%s' name='%s'\n", ea_endpoint->ep_serial, (id)?id:"NULL", itype, ntype, present, screen, (extension)?extension:"NULL", (name)?name:"NULL");
346 /* NOTE: is caller is is not available for this extesion, it has been removed by apply_callerid_restriction already */
348 /* internal extension's caller id */
349 if (extension[0] && e_ext.display_int)
352 SCAT(display, extension);
355 if (itype == INFO_ITYPE_VBOX)
356 SCAT(display, "(vbox)");
358 SCAT(display, "(int)");
361 /* external caller id */
362 if (!extension[0] && e_ext.display_ext)
368 if (present == INFO_PRESENT_RESTRICTED)
369 SCAT(display, "anonymous");
371 SCAT(display, "unknown");
378 /* display if callerid is anonymouse but available due anon-ignore */
379 if (e_ext.display_anon && present==INFO_PRESENT_RESTRICTED)
382 SCAT(display, "unknown");
385 SCAT(display, " anon");
388 /* display if callerid is anonymouse but available due anon-ignore */
389 if (e_ext.display_fake && screen==INFO_SCREEN_USER && ntype!=INFO_NTYPE_NOTPRESENT)
395 if (present == INFO_PRESENT_RESTRICTED)
396 SCAT(display, "anonymous");
398 SCAT(display, "unknown");
403 SCAT(display, " fake");
407 if (name[0] && e_ext.display_name)
409 if (!display[0] && cid[0])
420 * uses the current state to notify activity
422 void EndpointAppPBX::notify_active(void)
424 struct port_list *portlist = ea_endpoint->ep_portlist;
425 struct lcr_msg *message;
430 case NOTIFY_STATE_ACTIVE:
431 /* we are already active, so we don't do anything */
434 case NOTIFY_STATE_SUSPEND:
435 notify = INFO_NOTIFY_USER_RESUMED;
438 set_tone(portlist, NULL);
439 portlist = portlist->next;
441 portlist = ea_endpoint->ep_portlist;
444 case NOTIFY_STATE_HOLD:
445 notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
448 set_tone(portlist, NULL);
449 portlist = portlist->next;
451 portlist = ea_endpoint->ep_portlist;
454 case NOTIFY_STATE_CONFERENCE:
455 notify = INFO_NOTIFY_CONFERENCE_DISCONNECTED;
458 set_tone(portlist, NULL);
459 portlist = portlist->next;
461 portlist = ea_endpoint->ep_portlist;
465 PERROR("unknown e_tx_state = %d\n", e_tx_state);
471 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
472 message->param.notifyinfo.notify = notify;
473 message_put(message);
474 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
475 portlist = portlist->next;
481 * keypad functions during call. one example to use this is to put a call on hold or start a conference
483 void EndpointAppPBX::keypad_function(char digit)
486 /* we must be in a call, in order to send messages to the call */
487 if (e_ext.number[0] == '\0')
489 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) IGNORING keypad received not from extension.\n", ea_endpoint->ep_serial);
495 /* join conference */
497 if (ea_endpoint->ep_join_id == 0)
499 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad received during connect but not during a call.\n", ea_endpoint->ep_serial);
502 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join call with call on hold\n", ea_endpoint->ep_serial);
508 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) shared key encryption selected.\n", ea_endpoint->ep_serial);
512 /* crypt key-exchange */
514 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) key exchange encryption selected.\n", ea_endpoint->ep_serial);
520 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) encryption off selected.\n", ea_endpoint->ep_serial);
525 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) unsupported keypad digit '%c'.\n", ea_endpoint->ep_serial, digit);
530 /* set tone pattern for port */
531 void EndpointAppPBX::set_tone(struct port_list *portlist, const char *tone)
533 struct lcr_msg *message;
538 /* store for suspended processes */
542 if (e_join_pattern /* pattern are provided */
543 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_SETUP)
544 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_OVERLAP)
545 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_IN_PROCEEDING)
546 && !(e_ext.own_alerting && e_state == EPOINT_STATE_IN_ALERTING)
547 && !(e_ext.own_cause && e_state == EPOINT_STATE_IN_DISCONNECT)
548 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_SETUP)
549 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_OVERLAP)
550 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_OUT_PROCEEDING)
551 && !(e_ext.own_alerting && e_state == EPOINT_STATE_OUT_ALERTING)
552 && !(e_ext.own_cause && e_state == EPOINT_STATE_OUT_DISCONNECT)
553 && tone[0] && !!strncmp(tone,"crypt_*",6))
555 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) tone not provided since patterns are available\n", ea_endpoint->ep_serial);
561 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_TONE);
562 SCPY(message->param.tone.dir, e_ext.tones_dir[0]?e_ext.tones_dir:options.tones_dir);
563 SCPY(message->param.tone.name, tone);
564 message_put(message);
565 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
568 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port to notify tone.\n", ea_endpoint->ep_serial);
575 * hunts an mISDNport that is available for an outgoing call
576 * if no ifname was given, any interface that is not an extension
579 struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel)
581 struct interface *interface;
582 struct interface_port *ifport, *ifport_start;
583 struct select_channel *selchannel;
584 struct mISDNport *mISDNport;
587 interface = interface_first;
589 /* first find the given interface or, if not given, one with no extension */
594 /* check for given interface */
597 if (!strcasecmp(interface->name, ifname))
599 /* found explicit interface */
600 trace_header("CHANNEL SELECTION (found interface)", DIRECTION_NONE);
601 add_trace("interface", NULL, "%s", ifname);
608 if (!interface->extension)
610 /* found non extension */
611 trace_header("CHANNEL SELECTION (found non extension interface)", DIRECTION_NONE);
612 add_trace("interface", NULL, "%s", interface->name);
618 interface = interface->next;
622 /* see if interface has ports */
623 if (!interface->ifport)
626 trace_header("CHANNEL SELECTION (active ports, skipping)", DIRECTION_NONE);
627 add_trace("interface", NULL, "%s", interface->name);
629 interface = interface->next;
633 /* select port by algorithm */
634 ifport_start = interface->ifport;
636 if (interface->hunt == HUNT_ROUNDROBIN)
638 while(ifport_start->next && index<interface->hunt_next)
640 ifport_start = ifport_start->next;
643 trace_header("CHANNEL SELECTION (starting round-robin)", DIRECTION_NONE);
644 add_trace("port", NULL, "%d", ifport_start->portnum);
645 add_trace("position", NULL, "%d", index);
650 ifport = ifport_start;
653 /* see if port is available */
654 if (!ifport->mISDNport)
656 trace_header("CHANNEL SELECTION (port not available, skipping)", DIRECTION_NONE);
657 add_trace("port", NULL, "%d", ifport->portnum);
658 add_trace("position", NULL, "%d", index);
662 mISDNport = ifport->mISDNport;
664 /* see if port is administratively blocked */
667 trace_header("CHANNEL SELECTION (port blocked by admin, skipping)", DIRECTION_NONE);
668 add_trace("port", NULL, "%d", ifport->portnum);
669 add_trace("position", NULL, "%d", index);
674 /* see if link is up on PTP*/
675 if (mISDNport->l2hold && mISDNport->l2link<1)
677 trace_header("CHANNEL SELECTION (port's layer 2 is down, skipping)", DIRECTION_NONE);
678 add_trace("port", NULL, "%d", ifport->portnum);
679 add_trace("position", NULL, "%d", index);
684 /* check for channel form selection list */
686 selchannel = ifport->out_channel;
689 switch(selchannel->channel)
691 case CHANNEL_FREE: /* free channel */
692 if (mISDNport->b_reserved >= mISDNport->b_num)
693 break; /* all channel in use or reserverd */
696 while(i < mISDNport->b_num)
698 if (mISDNport->b_port[i] == NULL)
700 *channel = i+1+(i>=15);
701 trace_header("CHANNEL SELECTION (selecting free channel)", DIRECTION_NONE);
702 add_trace("port", NULL, "%d", ifport->portnum);
703 add_trace("position", NULL, "%d", index);
704 add_trace("channel", NULL, "%d", *channel);
712 trace_header("CHANNEL SELECTION (no channel is 'free')", DIRECTION_NONE);
713 add_trace("port", NULL, "%d", ifport->portnum);
714 add_trace("position", NULL, "%d", index);
718 case CHANNEL_ANY: /* don't ask for channel */
719 if (mISDNport->b_reserved >= mISDNport->b_num)
721 trace_header("CHANNEL SELECTION (cannot ask for 'any' channel, all reserved)", DIRECTION_NONE);
722 add_trace("port", NULL, "%d", ifport->portnum);
723 add_trace("position", NULL, "%d", index);
724 add_trace("total", NULL, "%d", mISDNport->b_num);
725 add_trace("reserved", NULL, "%d", mISDNport->b_reserved);
727 break; /* all channel in use or reserverd */
729 trace_header("CHANNEL SELECTION (using 'any' channel)", DIRECTION_NONE);
730 add_trace("port", NULL, "%d", ifport->portnum);
731 add_trace("position", NULL, "%d", index);
733 *channel = CHANNEL_ANY;
736 case CHANNEL_NO: /* call waiting */
737 trace_header("CHANNEL SELECTION (using 'no' channel, call-waiting)", DIRECTION_NONE);
738 add_trace("port", NULL, "%d", ifport->portnum);
739 add_trace("position", NULL, "%d", index);
741 *channel = CHANNEL_NO;
745 if (selchannel->channel<1 || selchannel->channel==16)
747 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
748 add_trace("port", NULL, "%d", ifport->portnum);
749 add_trace("position", NULL, "%d", index);
750 add_trace("channel", NULL, "%d", selchannel->channel);
752 break; /* invalid channels */
754 i = selchannel->channel-1-(selchannel->channel>=17);
755 if (i >= mISDNport->b_num)
757 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
758 add_trace("port", NULL, "%d", ifport->portnum);
759 add_trace("position", NULL, "%d", index);
760 add_trace("channel", NULL, "%d", selchannel->channel);
761 add_trace("channels", NULL, "%d", mISDNport->b_num);
763 break; /* channel not in port */
765 if (mISDNport->b_port[i] == NULL)
767 *channel = selchannel->channel;
768 trace_header("CHANNEL SELECTION (selecting given channel)", DIRECTION_NONE);
769 add_trace("port", NULL, "%d", ifport->portnum);
770 add_trace("position", NULL, "%d", index);
771 add_trace("channel", NULL, "%d", *channel);
778 break; /* found channel */
779 selchannel = selchannel->next;
782 /* if channel was found, return mISDNport and channel */
785 /* setting next port to start next time */
786 if (interface->hunt == HUNT_ROUNDROBIN)
791 interface->hunt_next = index;
797 trace_header("CHANNEL SELECTION (skipping, no channel found)", DIRECTION_NONE);
798 add_trace("port", NULL, "%d", ifport->portnum);
799 add_trace("position", NULL, "%d", index);
803 /* go next port, until all ports are checked */
805 ifport = ifport->next;
809 ifport = interface->ifport;
811 if (ifport != ifport_start)
815 interface = interface->next;
819 return(NULL); /* no port found */
822 /* outgoing setup to port(s)
823 * ports will be created and a setup is sent if everything is ok. otherwhise
824 * the endpoint is destroyed.
826 void EndpointAppPBX::out_setup(void)
828 struct dialing_info dialinginfo;
830 // class pdss1 *pdss1;
831 struct port_list *portlist;
832 struct lcr_msg *message;
834 int cause = CAUSE_RESSOURCEUNAVAIL;
837 struct mISDNport *mISDNport;
840 class EndpointAppPBX *atemp;
841 // char allowed_ports[256];
843 char ifname[sizeof(e_ext.interfaces)],
845 struct port_settings port_settings;
848 int mode = B_MODE_TRANSPARENT;
850 /* set bchannel mode */
851 mode = e_capainfo.source_mode;
853 /* create settings for creating port */
854 memset(&port_settings, 0, sizeof(port_settings));
856 SCPY(port_settings.tones_dir, e_ext.tones_dir);
858 SCPY(port_settings.tones_dir, options.tones_dir);
859 port_settings.no_seconds = e_ext.no_seconds;
861 /* NOTE: currently the try_card feature is not supported. it should be used later to try another card, if the outgoing call fails on one port */
863 /* check what dialinginfo.itype we got */
864 switch(e_dialinginfo.itype)
866 /* *********************** call to extension or vbox */
867 case INFO_ITYPE_ISDN_EXTENSION:
868 /* check if we deny incoming calls when we use an extension */
869 if (e_ext.noknocking)
871 atemp = apppbx_first;
875 if (!strcmp(atemp->e_ext.number, e_ext.number))
881 PERROR("EPOINT(%d) noknocking and currently a call\n", ea_endpoint->ep_serial);
882 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYSPE_ join, port */
883 return; /* must exit here */
886 /* FALL THROUGH !!!! */
887 case INFO_ITYPE_VBOX:
888 /* get dialed extension's info */
889 // SCPY(exten, e_dialinginfo.id);
890 // if (strchr(exten, ','))
891 // *strchr(exten, ',') = '\0';
892 // if (!read_extension(&e_ext, exten))
893 if (!read_extension(&e_ext, e_dialinginfo.id))
895 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) extension %s not configured\n", ea_endpoint->ep_serial, e_dialinginfo.id);
896 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
897 return; /* must exit here */
900 if (e_dialinginfo.itype == INFO_ITYPE_VBOX)
902 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing directly to VBOX\n", ea_endpoint->ep_serial);
907 /* string from unconditional call forward (cfu) */
911 /* present to forwarded party */
912 if (e_ext.anon_ignore && e_callerinfo.id[0])
914 e_callerinfo.present = INFO_PRESENT_ALLOWED;
916 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
920 /* string from busy call forward (cfb) */
924 class EndpointAppPBX *checkapp = apppbx_first;
927 if (checkapp != this) /* any other endpoint except our own */
929 if (!strcmp(checkapp->e_ext.number, e_ext.number))
931 /* present to forwarded party */
932 if (e_ext.anon_ignore && e_callerinfo.id[0])
934 e_callerinfo.present = INFO_PRESENT_ALLOWED;
936 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
940 checkapp = checkapp->next;
944 /* string from no-response call forward (cfnr) */
948 /* when cfnr is done, out_setup() will setup the call */
951 /* present to forwarded party */
952 if (e_ext.anon_ignore && e_callerinfo.id[0])
954 e_callerinfo.present = INFO_PRESENT_ALLOWED;
958 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
960 e_cfnr_release = now + e_ext.cfnr_delay;
961 e_cfnr_call = now + e_ext.cfnr_delay + 1; /* call one second after release */
962 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) setting time for call-forward-busy to %s with delay %ld.\n", ea_endpoint->ep_serial, e_ext.cfnr, e_ext.cfnr_delay);
966 /* call to all internal interfaces */
967 p = e_ext.interfaces;
968 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) generating multiple joins for extension %s to interfaces %s\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
972 while(*p!=',' && *p!='\0')
977 /* found interface */
978 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
979 /* hunt for mISDNport and create Port */
980 mISDNport = hunt_port(ifname, &channel);
983 trace_header("INTERFACE (not found or busy)", DIRECTION_NONE);
984 add_trace("interface", NULL, "%s", ifname);
988 /* creating INTERNAL port */
989 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
990 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
992 FATAL("No memory for DSS1 Port instance\n");
993 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
994 memset(&dialinginfo, 0, sizeof(dialinginfo));
995 SCPY(dialinginfo.id, e_dialinginfo.id);
996 dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
997 dialinginfo.ntype = e_dialinginfo.ntype;
998 /* create port_list relation */
999 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
1002 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1004 goto check_anycall_intern;
1006 /* directory.list */
1007 if (e_callerinfo.id[0] && e_ext.display_name)
1009 dirname = parse_directory(e_callerinfo.id, e_callerinfo.ntype);
1011 SCPY(e_callerinfo.name, dirname);
1013 // dss1 = (class Pdss1 *)port;
1015 //printf("INTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1016 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1017 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1018 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1019 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1020 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1021 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1022 //terminal if (e_dialinginfo.id)
1023 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1024 /* handle restricted caller ids */
1025 apply_callerid_restriction(&e_ext, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
1026 apply_callerid_restriction(&e_ext, message->param.setup.callerinfo.id2, &message->param.setup.callerinfo.ntype2, &message->param.setup.callerinfo.present2, &message->param.setup.callerinfo.screen2, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
1027 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);
1028 /* display callerid if desired for extension */
1029 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));
1030 //printf("\n\ndisplay = %s\n\n\n",message->param.setup.callerinfo.display);
1031 /* use cnip, if enabld */
1032 // if (!e_ext.centrex)
1033 // message->param.setup.callerinfo.name[0] = '\0';
1034 /* screen clip if prefix is required */
1035 if (message->param.setup.callerinfo.id[0] && e_ext.clip_prefix[0])
1037 SCPY(message->param.setup.callerinfo.id, e_ext.clip_prefix);
1038 SCAT(message->param.setup.callerinfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype, options.national, options.international));
1039 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1041 if (message->param.setup.callerinfo.id2[0] && e_ext.clip_prefix[0])
1043 SCPY(message->param.setup.callerinfo.id2, e_ext.clip_prefix);
1044 SCAT(message->param.setup.callerinfo.id2, numberrize_callerinfo(e_callerinfo.id2,e_callerinfo.ntype2, options.national, options.international));
1045 message->param.setup.callerinfo.ntype2 = INFO_NTYPE_UNKNOWN;
1047 /* use internal caller id */
1048 if (e_callerinfo.extension[0] && (message->param.setup.callerinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
1050 SCPY(message->param.setup.callerinfo.id, e_callerinfo.extension);
1051 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1052 message->param.setup.callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
1054 message_put(message);
1055 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1059 /* string from parallel call forward (cfp) */
1063 if (e_ext.anon_ignore && e_callerinfo.id[0])
1065 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1066 e_callerinfo.present2 = INFO_PRESENT_ALLOWED;
1070 vbox_only: /* entry point for answering machine only */
1071 cfu_only: /* entry point for cfu */
1072 cfb_only: /* entry point for cfb */
1073 cfnr_only: /* entry point for cfnr */
1074 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call extension %s for external destiantion(s) '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
1079 /* only if vbox should be dialed, and terminal is given */
1080 if (!strcmp(p, "vbox") && e_ext.number[0])
1082 /* go to the end of p */
1085 /* answering vbox call */
1086 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) answering machine\n", ea_endpoint->ep_serial);
1088 if (!(port = new VBoxPort(PORT_TYPE_VBOX_OUT, &port_settings)))
1089 FATAL("No memory for VBOX Port instance\n");
1090 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocated port %s\n", ea_endpoint->ep_serial, port->p_name);
1091 UCPY(cfp, e_ext.number); /* cfp or any other direct forward/vbox */
1095 while(*p!=',' && *p!='\0')
1100 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cfp external %s\n", ea_endpoint->ep_serial, cfp);
1101 /* hunt for mISDNport and create Port */
1102 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1105 /* creating EXTERNAL port*/
1106 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1107 if (!(port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode)))
1108 FATAL("No memory for DSS1 Port instance\n");
1109 earlyb = mISDNport->earlyb;
1113 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1114 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1120 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port found or created, which is idle.\n", ea_endpoint->ep_serial);
1121 goto check_anycall_intern;
1123 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found or created port %s\n", ea_endpoint->ep_serial, port->p_name);
1124 memset(&dialinginfo, 0, sizeof(dialinginfo));
1125 SCPY(dialinginfo.id, cfp);
1126 dialinginfo.itype = INFO_ITYPE_ISDN;
1127 dialinginfo.ntype = e_dialinginfo.ntype;
1128 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
1131 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1133 goto check_anycall_intern;
1135 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1136 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1137 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1138 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1139 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1140 /* if clip is hidden */
1141 if (e_ext.clip==CLIP_HIDE && port->p_type!=PORT_TYPE_VBOX_OUT)
1143 SCPY(message->param.setup.callerinfo.id, e_ext.callerid);
1144 SCPY(message->param.setup.callerinfo.extension, e_ext.number);
1145 message->param.setup.callerinfo.ntype = e_ext.callerid_type;
1146 message->param.setup.callerinfo.present = e_ext.callerid_present;
1147 message->param.setup.callerinfo.ntype = INFO_NTYPE_NOTPRESENT;
1149 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1150 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1151 //terminal if (e_dialinginfo.id)
1152 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1153 /* handle restricted caller ids */
1154 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);
1155 apply_callerid_restriction(&e_ext, message->param.setup.callerinfo.id2, &message->param.setup.callerinfo.ntype2, &message->param.setup.callerinfo.present2, &message->param.setup.callerinfo.screen2, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
1156 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);
1157 /* display callerid if desired for extension */
1158 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));
1159 message_put(message);
1160 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1164 check_anycall_intern:
1165 /* now we have all ports created */
1168 trace_header("INTERFACE (no extension's interface)", DIRECTION_NONE);
1170 if (!ea_endpoint->ep_join_id)
1172 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1173 return; /* must exit here */
1177 /* *********************** external call */
1179 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id);
1180 /* call to extenal interfaces */
1181 p = e_dialinginfo.id;
1185 while(*p!=',' && *p!='\0')
1186 SCCAT(number, *p++);
1190 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");
1191 /* hunt for mISDNport and create Port */
1192 /* hunt for mISDNport and create Port */
1193 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1196 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1197 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1199 goto check_anycall_extern;
1201 /* creating EXTERNAL port*/
1202 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1203 if (!(port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode)))
1204 FATAL("No memory for DSS1 Port instance\n");
1205 earlyb = mISDNport->earlyb;
1206 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
1207 memset(&dialinginfo, 0, sizeof(dialinginfo));
1208 SCPY(dialinginfo.id, number);
1209 dialinginfo.itype = INFO_ITYPE_ISDN;
1210 dialinginfo.ntype = e_dialinginfo.ntype;
1211 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
1214 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1216 goto check_anycall_extern;
1218 // dss1 = (class Pdss1 *)port;
1219 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1220 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1221 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1222 SCPY(message->param.setup.dialinginfo.id, number);
1223 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1224 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1225 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1226 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1227 //terminal if (e_dialinginfo.id)
1228 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1229 /* handle restricted caller ids */
1230 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);
1231 apply_callerid_restriction(&e_ext, message->param.setup.callerinfo.id2, &message->param.setup.callerinfo.ntype2, &message->param.setup.callerinfo.present2, &message->param.setup.callerinfo.screen2, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
1232 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);
1233 /* display callerid if desired for extension */
1234 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));
1235 message_put(message);
1236 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1240 check_anycall_extern:
1241 /* now we have all ports created */
1244 trace_header("INTERFACE (no free ports found)", DIRECTION_NONE);
1246 if (!ea_endpoint->ep_join_id)
1248 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1249 return; /* must exit here */
1257 /* handler for endpoint
1261 int EndpointAppPBX::handler(void)
1263 if (e_crypt_state!=CM_ST_NULL)
1268 /* process answering machine (play) handling */
1271 if (e_action->index == ACTION_VBOX_PLAY)
1274 /* process action timeout */
1275 if (e_action_timeout)
1276 if (now_d >= e_action_timeout)
1278 if (e_state!=EPOINT_STATE_CONNECT)
1281 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current action timed out.\n", ea_endpoint->ep_serial);
1282 e_multipoint_cause = 0;
1283 e_multipoint_location = 0;
1284 new_state(EPOINT_STATE_IN_OVERLAP);
1287 return(1); /* we must exit, because our endpoint might be gone */
1289 e_action_timeout = 0;
1292 /* process action timeout */
1293 if (e_match_timeout)
1294 if (now_d >= e_match_timeout)
1297 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we got a match timeout.\n", ea_endpoint->ep_serial);
1299 return(1); /* we must exit, because our endpoint might be gone */
1304 /* process redialing (epoint redials to port) */
1307 if (now_d >= e_redial)
1310 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial.\n", ea_endpoint->ep_serial);
1312 new_state(EPOINT_STATE_OUT_SETUP);
1313 /* call special setup routine */
1320 /* process powerdialing (epoint redials to epoint) */
1321 if (e_powerdialing > 0)
1323 if (now_d >= e_powerdialing)
1325 e_powerdialing = -1; /* leave power dialing on */
1326 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial of powerdial.\n", ea_endpoint->ep_serial);
1329 e_ruleset = ruleset_main;
1331 e_rule = e_ruleset->rule_first;
1333 new_state(EPOINT_STATE_IN_OVERLAP);
1339 /* process call forward no response */
1342 struct port_list *portlist;
1343 struct lcr_msg *message;
1345 if (now >= e_cfnr_release)
1347 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-no-response time has expired, hanging up.\n", ea_endpoint->ep_serial);
1350 /* release all ports */
1351 while((portlist = ea_endpoint->ep_portlist))
1353 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1354 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
1355 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1356 message_put(message);
1357 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1358 ea_endpoint->free_portlist(portlist);
1361 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1362 message->param.audiopath = 0;
1363 message_put(message);
1364 /* indicate no patterns */
1365 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1366 message_put(message);
1367 /* set setup state, since we have no response from the new join */
1368 new_state(EPOINT_STATE_OUT_SETUP);
1373 if (now >= e_cfnr_call)
1375 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-busy time has expired, calling the forwarded number: %s.\n", ea_endpoint->ep_serial, e_ext.cfnr);
1381 /* handle connection to user */
1382 if (e_state == EPOINT_STATE_IDLE)
1384 /* epoint is idle, check callback */
1386 if (now_d >= e_callback)
1388 e_callback = 0; /* done with callback */
1389 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting callback.\n", ea_endpoint->ep_serial);
1390 new_state(EPOINT_STATE_OUT_SETUP);
1396 /* check for password timeout */
1398 if (e_action->index==ACTION_PASSWORD || e_action->index==ACTION_PASSWORD_WRITE)
1400 struct port_list *portlist;
1402 if (now >= e_password_timeout)
1404 e_ruleset = ruleset_main;
1406 e_rule = e_ruleset->rule_first;
1408 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) password timeout %s\n", ea_endpoint->ep_serial, e_extdialing);
1409 trace_header("PASSWORD timeout", DIRECTION_NONE);
1411 e_connectedmode = 0;
1413 new_state(EPOINT_STATE_OUT_DISCONNECT);
1414 portlist = ea_endpoint->ep_portlist;
1417 message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
1418 set_tone(portlist, "cause_10");
1428 /* doing a hookflash */
1429 void EndpointAppPBX::hookflash(void)
1433 /* be sure that we are active */
1435 e_tx_state = NOTIFY_STATE_ACTIVE;
1437 trace_header("HOOKFLASH DTMF", DIRECTION_NONE);
1439 if (ea_endpoint->ep_use > 1)
1441 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot hooflash while child process is running.\n", ea_endpoint->ep_serial);
1444 /* dialtone after pressing the hash key */
1445 process_hangup(e_join_cause, e_join_location);
1446 e_multipoint_cause = 0;
1447 e_multipoint_location = 0;
1448 port = find_port_id(ea_endpoint->ep_portlist->port_id);
1451 port->set_echotest(0);
1453 if (ea_endpoint->ep_join_id)
1455 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1457 e_ruleset = ruleset_main;
1459 e_rule = e_ruleset->rule_first;
1461 new_state(EPOINT_STATE_IN_OVERLAP);
1462 e_connectedmode = 1;
1463 SCPY(e_dialinginfo.id, e_ext.prefix);
1464 e_extdialing = e_dialinginfo.id;
1466 if (e_dialinginfo.id[0])
1468 set_tone(ea_endpoint->ep_portlist, "dialing");
1472 set_tone(ea_endpoint->ep_portlist, "dialpbx");
1479 /* messages from port
1481 /* port MESSAGE_SETUP */
1482 void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, union parameter *param)
1484 struct lcr_msg *message;
1486 int writeext; /* flags need to write extension after modification */
1488 struct interface *interface;
1490 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1492 portlist->port_type = param->setup.port_type;
1493 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
1494 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
1495 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
1496 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
1497 // e_dtmf = param->setup.dtmf;
1498 /* screen incoming caller id */
1499 interface = interface_first;
1502 if (!strcmp(e_callerinfo.interface, interface->name))
1506 interface = interface->next;
1509 do_screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface);
1510 do_screen(0, e_callerinfo.id2, sizeof(e_callerinfo.id2), &e_callerinfo.ntype2, &e_callerinfo.present2, interface);
1513 /* process extension */
1514 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1516 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is extension\n", ea_endpoint->ep_serial);
1517 /* port makes call from extension */
1518 SCPY(e_callerinfo.extension, e_callerinfo.id);
1519 SCPY(e_ext.number, e_callerinfo.extension);
1520 SCPY(e_extension_interface, e_callerinfo.interface);
1523 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is external or voip\n", ea_endpoint->ep_serial);
1526 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1528 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1530 /* get extension's info about caller */
1531 if (!read_extension(&e_ext, e_ext.number))
1533 /* extension doesn't exist */
1534 trace_header("EXTENSION (not created)", DIRECTION_IN);
1535 add_trace("extension", NULL, "%s", e_ext.number);
1537 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
1538 new_state(EPOINT_STATE_OUT_DISCONNECT);
1539 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
1540 e_ext.number[0] = '\0'; /* no terminal */
1545 /* put prefix (next) in front of e_dialinginfo.id */
1548 SPRINT(buffer, "%s%s", e_ext.next, e_dialinginfo.id);
1549 SCPY(e_dialinginfo.id, buffer);
1550 e_ext.next[0] = '\0';
1552 } else if (e_ext.prefix[0])
1554 SPRINT(buffer, "%s%s", e_ext.prefix, e_dialinginfo.id);
1555 SCPY(e_dialinginfo.id, buffer);
1558 /* screen caller id by extension's config */
1559 e_callerinfo.screen = INFO_SCREEN_NETWORK;
1561 SCPY(e_callerinfo.name, e_ext.name);
1562 /* use caller id (or if exist: id_next_call) for this call */
1563 if (e_ext.id_next_call_present >= 0)
1565 SCPY(e_callerinfo.id, e_ext.id_next_call);
1566 /* if we restrict the pesentation */
1567 if (e_ext.id_next_call_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1568 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1569 else e_callerinfo.present = e_ext.id_next_call_present;
1570 e_callerinfo.ntype = e_ext.id_next_call_type;
1571 e_ext.id_next_call_present = -1;
1575 SCPY(e_callerinfo.id, e_ext.callerid);
1576 /* if we restrict the pesentation */
1577 if (e_ext.callerid_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1578 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1579 else e_callerinfo.present = e_ext.callerid_present;
1580 e_callerinfo.ntype = e_ext.callerid_type;
1582 e_callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
1584 /* extension is written */
1586 write_extension(&e_ext, e_ext.number);
1588 /* set volume of rx and tx */
1589 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1590 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
1592 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
1593 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
1594 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
1595 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
1596 message_put(message);
1599 /* start recording if enabled */
1600 if (e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO))
1602 /* check if we are a terminal */
1603 if (e_ext.number[0] == '\0')
1604 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
1607 port = find_port_id(portlist->port_id);
1609 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
1614 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from external port\n", ea_endpoint->ep_serial);
1615 /* no terminal identification */
1616 e_ext.number[0] = '\0';
1617 e_extension_interface[0] = '\0';
1618 memset(&e_ext, 0, sizeof(e_ext));
1619 e_ext.rights = 4; /* right to dial internat */
1623 e_ruleset = ruleset_main;
1625 e_rule = e_ruleset->rule_first;
1627 e_extdialing = e_dialinginfo.id;
1628 new_state(EPOINT_STATE_IN_SETUP);
1629 if (e_dialinginfo.id[0])
1631 set_tone(portlist, "dialing");
1634 if (e_ext.number[0])
1635 set_tone(portlist, "dialpbx");
1637 set_tone(portlist, "dialtone");
1640 if (e_state == EPOINT_STATE_IN_SETUP)
1642 /* request MORE info, if not already at higher state */
1643 new_state(EPOINT_STATE_IN_OVERLAP);
1644 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_OVERLAP);
1645 message_put(message);
1646 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1650 /* port MESSAGE_INFORMATION */
1651 void EndpointAppPBX::port_information(struct port_list *portlist, int message_type, union parameter *param)
1653 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1655 /* ignore information message without digit information */
1656 if (!param->information.id[0])
1661 /* turn off dtmf detection, in case dtmf is sent with keypad information */
1664 trace_header("DTMF (disabling due to keypad)", DIRECTION_IN);
1669 /* if vbox_play is done, the information are just used as they come */
1671 if (e_action->index == ACTION_VBOX_PLAY)
1673 /* concat dialing string */
1674 SCAT(e_dialinginfo.id, param->information.id);
1679 /* keypad when disconnect but in connected mode */
1680 if (e_state==EPOINT_STATE_OUT_DISCONNECT && e_connectedmode)
1682 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received after disconnect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1683 /* processing keypad function */
1684 if (param->information.id[0] == '0')
1691 /* keypad when connected */
1692 if (e_state == EPOINT_STATE_CONNECT)
1694 if (e_ext.keypad || e_enablekeypad)
1696 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1697 /* processing keypad function */
1698 if (param->information.id[0] == '0')
1702 if (param->information.id[0])
1703 keypad_function(param->information.id[0]);
1706 if (e_ext.number[0])
1707 trace_header("KEYPAD (not enabled by extension's settings)", DIRECTION_IN);
1709 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1714 if (e_state != EPOINT_STATE_IN_OVERLAP)
1716 if (e_ext.number[0])
1717 trace_header("KEYPAD (ignored, not connected and not dialing)", DIRECTION_IN);
1719 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1723 if (!param->information.id[0])
1725 if (e_dialinginfo.id[0]=='\0' && !e_action)
1727 set_tone(portlist, "dialing");
1730 if (e_action->index==ACTION_OUTDIAL
1731 || e_action->index==ACTION_EXTERNAL
1732 || e_action->index==ACTION_REMOTE)
1735 set_tone(portlist, "dialing");
1736 else if (!e_extdialing[0])
1737 set_tone(portlist, "dialing");
1739 /* concat dialing string */
1740 SCAT(e_dialinginfo.id, param->information.id);
1744 /* port MESSAGE_DTMF */
1745 void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
1747 /* only if dtmf detection is enabled */
1750 trace_header("DTMF (disabled)", DIRECTION_IN);
1754 trace_header("DTMF", DIRECTION_IN);
1755 add_trace("digit", NULL, "%c", param->dtmf);
1759 NOTE: vbox is now handled due to overlap state
1760 /* if vbox_play is done, the dtmf digits are just used as they come */
1762 if (e_action->index == ACTION_VBOX_PLAY)
1764 /* concat dialing string */
1765 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id))
1767 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1768 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1771 /* continue to process *X# sequences */
1775 /* check for *X# sequence */
1776 if (e_state == EPOINT_STATE_CONNECT)
1778 if (e_dtmf_time+3 < now)
1780 /* the last digit was too far in the past to be a sequence */
1781 if (param->dtmf == '*')
1782 /* only start is allowed in the sequence */
1788 /* we have a sequence of digits, see what we got */
1789 if (param->dtmf == '*')
1791 else if (param->dtmf>='0' && param->dtmf<='9')
1793 /* we need to have a star before we receive the digit of the sequence */
1794 if (e_dtmf_last == '*')
1795 e_dtmf_last = param->dtmf;
1796 } else if (param->dtmf == '#')
1799 if (e_dtmf_last>='0' && e_dtmf_last<='9')
1801 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf sequence *%c# detected.\n", ea_endpoint->ep_serial, e_dtmf_last);
1802 if (e_dtmf_last == '0')
1807 /* processing keypad function */
1809 keypad_function(e_dtmf_last);
1815 /* set last time of dtmf */
1820 /* check for ## hookflash during dialing */
1822 if (e_action->index==ACTION_PASSWORD
1823 || e_action->index==ACTION_PASSWORD_WRITE)
1825 if (param->dtmf=='#') /* current digit is '#' */
1827 if (e_state==EPOINT_STATE_IN_DISCONNECT
1828 || (e_state!=EPOINT_STATE_CONNECT && e_dtmf_time+3>=now && e_dtmf_last=='#')) /* when disconnected, just #. when dialing, ##. */
1845 /* dialing using dtmf digit */
1846 if (e_state==EPOINT_STATE_IN_OVERLAP)// && e_state==e_connectedmode)
1848 if (e_dialinginfo.id[0]=='\0' && !e_action)
1850 set_tone(portlist, "dialing");
1852 /* concat dialing string */
1853 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id))
1855 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1856 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1862 /* port MESSAGE_CRYPT */
1863 void EndpointAppPBX::port_crypt(struct port_list *portlist, int message_type, union parameter *param)
1865 /* send crypt response to cryptman */
1866 if (param->crypt.type == CR_MESSAGE_IND)
1867 cryptman_msg2man(param->crypt.data, param->crypt.len);
1869 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
1872 /* port MESSAGE_OVERLAP */
1873 void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, union parameter *param)
1875 struct lcr_msg *message;
1877 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1879 /* signal to call tool */
1880 admin_call_response(e_adminid, ADMIN_CALL_SETUP_ACK, "", 0, 0, 0);
1882 if (e_dialing_queue[0] && portlist)
1884 /* send what we have not dialed yet, because we had no setup complete */
1885 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing pending digits: '%s'\n", ea_endpoint->ep_serial, e_dialing_queue);
1886 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
1887 SCPY(message->param.information.id, e_dialing_queue);
1888 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
1889 message_put(message);
1890 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
1891 e_dialing_queue[0] = '\0';
1893 /* check if pattern is available */
1894 if (!ea_endpoint->ep_portlist->next && portlist->early_b) /* one port_list relation and tones available */
1896 /* indicate patterns */
1897 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1898 message_put(message);
1900 /* connect audio, if not already */
1901 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1902 message->param.audiopath = 1;
1903 message_put(message);
1906 /* indicate no patterns */
1907 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1908 message_put(message);
1910 /* disconnect audio, if not already */
1911 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1912 message->param.audiopath = 0;
1913 message_put(message);
1915 new_state(EPOINT_STATE_OUT_OVERLAP);
1916 /* if we are in a join */
1917 if (ea_endpoint->ep_join_id)
1919 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1920 memcpy(&message->param, param, sizeof(union parameter));
1921 message_put(message);
1925 /* port MESSAGE_PROCEEDING */
1926 void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_type, union parameter *param)
1928 struct lcr_msg *message;
1930 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1932 /* signal to call tool */
1933 admin_call_response(e_adminid, ADMIN_CALL_PROCEEDING, "", 0, 0, 0);
1935 e_state = EPOINT_STATE_OUT_PROCEEDING;
1936 /* check if pattern is availatle */
1937 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
1939 /* indicate patterns */
1940 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1941 message_put(message);
1943 /* connect audio, if not already */
1944 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1945 message->param.audiopath = 1;
1946 message_put(message);
1949 /* indicate no patterns */
1950 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1951 message_put(message);
1953 /* disconnect audio, if not already */
1954 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1955 message->param.audiopath = 0;
1956 message_put(message);
1958 /* if we are in a call */
1959 if (ea_endpoint->ep_join_id)
1961 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1962 memcpy(&message->param, param, sizeof(union parameter));
1963 message_put(message);
1967 /* port MESSAGE_ALERTING */
1968 void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type, union parameter *param)
1970 struct lcr_msg *message;
1972 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1974 /* signal to call tool */
1975 admin_call_response(e_adminid, ADMIN_CALL_ALERTING, "", 0, 0, 0);
1978 // set_tone(portlist, "hold");
1980 new_state(EPOINT_STATE_OUT_ALERTING);
1981 /* check if pattern is available */
1982 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
1984 /* indicate patterns */
1985 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1986 message_put(message);
1988 /* connect audio, if not already */
1989 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1990 message->param.audiopath = 1;
1991 message_put(message);
1994 /* indicate no patterns */
1995 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1996 message_put(message);
1998 /* disconnect audio, if not already */
1999 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2000 message->param.audiopath = 0;
2001 message_put(message);
2003 /* if we are in a call */
2004 if (ea_endpoint->ep_join_id)
2006 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2007 memcpy(&message->param, param, sizeof(union parameter));
2008 message_put(message);
2012 /* port MESSAGE_CONNECT */
2013 void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, union parameter *param)
2015 struct lcr_msg *message;
2017 unsigned int port_id = portlist->port_id;
2018 struct port_list *tportlist;
2020 struct interface *interface;
2022 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2024 /* signal to call tool */
2025 admin_call_response(e_adminid, ADMIN_CALL_CONNECT, numberrize_callerinfo(param->connectinfo.id,param->connectinfo.ntype, options.national, options.international), 0, 0, 0);
2027 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_connectinfo));
2028 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (start)\n", ea_endpoint->ep_serial);
2029 while(ea_endpoint->ep_portlist->next) /* as long as we have at least two ports */
2031 tportlist = ea_endpoint->ep_portlist;
2032 if (tportlist->port_id == port_id) /* if the first portlist is the calling one, the second must be a different one */
2033 tportlist = tportlist->next;
2034 if (tportlist->port_id == port_id)
2035 FATAL("EPOINT(%d) this should not happen since the portlist list must not have two links to the same port - exitting.\n");
2036 message = message_create(ea_endpoint->ep_serial, tportlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2037 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
2038 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2039 message_put(message);
2040 logmessage(message->type, &message->param, tportlist->port_id, DIRECTION_OUT);
2041 ea_endpoint->free_portlist(tportlist);
2043 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (end)\n", ea_endpoint->ep_serial);
2047 /* screen incoming connected id */
2048 interface = interface_first;
2051 if (!strcmp(e_connectinfo.interface, interface->name))
2055 interface = interface->next;
2058 do_screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface);
2060 /* screen connected name */
2062 SCPY(e_connectinfo.name, e_ext.name);
2064 /* add internal id to colp */
2065 SCPY(e_connectinfo.extension, e_ext.number);
2067 /* we store the connected port number */
2068 SCPY(e_extension_interface, e_connectinfo.interface);
2070 /* for internal and am calls, we get the extension's id */
2071 if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE)
2073 SCPY(e_connectinfo.id, e_ext.callerid);
2074 SCPY(e_connectinfo.extension, e_ext.number);
2075 e_connectinfo.itype = INFO_ITYPE_ISDN_EXTENSION;
2076 e_connectinfo.ntype = e_ext.callerid_type;
2077 e_connectinfo.present = e_ext.callerid_present;
2079 if (portlist->port_type==PORT_TYPE_VBOX_OUT)
2081 e_connectinfo.itype = INFO_ITYPE_VBOX;
2082 e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2085 new_state(EPOINT_STATE_CONNECT);
2087 /* set volume of rx and tx */
2088 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
2090 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2091 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2092 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
2093 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
2094 message_put(message);
2097 e_cfnr_call = e_cfnr_release = 0;
2098 if (e_ext.number[0])
2099 e_dtmf = 1; /* allow dtmf */
2102 /* other calls with no caller id (or not available for the extension) and force colp */
2103 if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE)
2105 e_connectinfo.ntype = INFO_NTYPE_NOTPRESENT;
2106 if (portlist->port_type==PORT_TYPE_DSS1_TE_OUT || portlist->port_type==PORT_TYPE_DSS1_NT_OUT) /* external extension answered */
2108 port = find_port_id(portlist->port_id);
2111 SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.id, &e_connectinfo.ntype, options.national, options.international));
2112 e_connectinfo.present = INFO_PRESENT_ALLOWED;
2117 /* send connect to join */
2118 if (ea_endpoint->ep_join_id)
2120 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2121 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
2122 message_put(message);
2124 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2125 message->param.audiopath = 1;
2126 message_put(message);
2127 } else if (!e_adminid)
2130 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have a callback, so we create a call with cbcaller: \"%s\".\n", ea_endpoint->ep_serial, e_cbcaller);
2131 SCPY(e_ext.number, e_cbcaller);
2132 new_state(EPOINT_STATE_IN_OVERLAP);
2133 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) callback from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2135 /* get extension's info about terminal */
2136 if (!read_extension(&e_ext, e_ext.number))
2138 /* extension doesn't exist */
2139 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2140 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
2141 new_state(EPOINT_STATE_OUT_DISCONNECT);
2142 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
2146 /* put prefix in front of e_cbdialing */
2147 SPRINT(buffer, "%s%s", e_ext.prefix, e_cbdialing);
2148 SCPY(e_dialinginfo.id, buffer);
2149 e_dialinginfo.itype = INFO_ITYPE_ISDN;
2150 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
2152 /* use caller id (or if exist: id_next_call) for this call */
2153 e_callerinfo.screen = INFO_SCREEN_NETWORK;
2154 SCPY(e_callerinfo.extension, e_ext.number);
2155 if (e_ext.id_next_call_present >= 0)
2157 SCPY(e_callerinfo.id, e_ext.id_next_call);
2158 e_callerinfo.present = e_ext.id_next_call_present;
2159 e_callerinfo.ntype = e_ext.id_next_call_type;
2160 e_ext.id_next_call_present = -1;
2161 /* extension is written */
2162 write_extension(&e_ext, e_ext.number);
2165 SCPY(e_callerinfo.id, e_ext.callerid);
2166 e_callerinfo.present = e_ext.callerid_present;
2167 e_callerinfo.ntype = e_ext.callerid_type;
2169 e_callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
2171 e_connectedmode = 1; /* dtmf-hangup & disconnect prevention */
2174 /* check if caller id is NOT authenticated */
2175 if (!parse_callbackauth(e_ext.number, &e_callbackinfo))
2177 /* make call state to enter password */
2178 new_state(EPOINT_STATE_IN_OVERLAP);
2179 e_action = &action_password_write;
2180 e_match_timeout = 0;
2181 e_match_to_action = NULL;
2182 e_dialinginfo.id[0] = '\0';
2183 e_extdialing = strchr(e_dialinginfo.id, '\0');
2184 e_password_timeout = now+20;
2188 /* incoming call (callback) */
2189 e_ruleset = ruleset_main;
2191 e_rule = e_ruleset->rule_first;
2193 e_extdialing = e_dialinginfo.id;
2194 if (e_dialinginfo.id[0])
2196 set_tone(portlist, "dialing");
2200 set_tone(portlist, "dialpbx");
2203 } else /* testcall */
2205 set_tone(portlist, "hold");
2208 /* start recording if enabled, not when answering machine answers */
2209 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))
2211 /* check if we are a terminal */
2212 if (e_ext.number[0] == '\0')
2213 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
2216 port = find_port_id(portlist->port_id);
2218 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
2223 /* port MESSAGE_DISCONNECT MESSAGE_RELEASE */
2224 void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
2226 struct lcr_msg *message;
2228 unsigned int port_id = portlist->port_id;
2232 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2234 /* signal to call tool */
2235 admin_call_response(e_adminid, (message_type==MESSAGE_DISCONNECT)?ADMIN_CALL_DISCONNECT:ADMIN_CALL_RELEASE, "", param->disconnectinfo.cause, param->disconnectinfo.location, 0);
2237 //#warning does this work? only disconnect when incoming port hat not already disconnected yet?
2238 if (e_state==EPOINT_STATE_IN_DISCONNECT && message_type!=MESSAGE_RELEASE)// || e_state==EPOINT_STATE_OUT_DISCONNECT || e_state==EPOINT_STATE_IDLE)
2240 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are already disconnected.\n", ea_endpoint->ep_serial);
2245 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);
2246 collect_cause(&e_multipoint_cause, &e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location);
2247 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new multipoint cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location);
2249 /* check if we have more than one portlist relation and we just ignore the disconnect */
2250 if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist->next)
2252 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the disconnect was from a multipoint call. we just release that relation.\n", ea_endpoint->ep_serial);
2253 portlist = ea_endpoint->ep_portlist;
2256 if (portlist->port_id == port_id)
2258 portlist = portlist->next;
2261 FATAL("EPOINT(%d) no portlist related to the calling port.\n", ea_endpoint->ep_serial);
2262 if (message_type != MESSAGE_RELEASE)
2264 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2265 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2266 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2267 message_put(message);
2268 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2270 ea_endpoint->free_portlist(portlist);
2271 return; /* one relation removed */
2273 if (e_state == EPOINT_STATE_CONNECT)
2275 /* use cause from port after connect */
2276 cause = param->disconnectinfo.cause;
2277 location = param->disconnectinfo.location;
2280 /* use multipoint cause if no connect yet */
2281 if (e_multipoint_cause)
2283 cause = e_multipoint_cause;
2284 location = e_multipoint_location;
2287 cause = CAUSE_NOUSER;
2288 location = LOCATION_PRIVATE_LOCAL;
2292 e_cfnr_call = e_cfnr_release = 0;
2294 /* process hangup */
2295 process_hangup(e_join_cause, e_join_location);
2296 e_multipoint_cause = 0;
2297 e_multipoint_location = 0;
2299 if (message_type == MESSAGE_DISCONNECT)
2301 /* tone to disconnected end */
2302 SPRINT(buffer, "cause_%02x", cause);
2303 if (ea_endpoint->ep_portlist)
2304 set_tone(ea_endpoint->ep_portlist, buffer);
2306 new_state(EPOINT_STATE_IN_DISCONNECT);
2309 if (ea_endpoint->ep_join_id)
2311 int haspatterns = 0;
2312 /* check if pattern is available */
2313 if (ea_endpoint->ep_portlist)
2314 if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->early_b)
2315 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
2316 && message_type != MESSAGE_RELEASE) // if we release, we are done
2320 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has patterns.\n", ea_endpoint->ep_serial);
2321 /* indicate patterns */
2322 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2323 message_put(message);
2324 /* connect audio, if not already */
2325 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2326 message->param.audiopath = 1;
2327 message_put(message);
2328 /* send disconnect */
2329 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2330 memcpy(&message->param, param, sizeof(union parameter));
2331 message_put(message);
2332 /* disable encryption if disconnected */
2333 //PERROR("REMOVE ME: state =%d, %d\n", e_crypt_state, e_crypt);
2335 cryptman_message(CI_DISCONNECT_IND, NULL, 0);
2339 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
2342 if (message_type == MESSAGE_RELEASE)
2343 ea_endpoint->free_portlist(portlist);
2344 release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, callcause, portcause */
2345 return; /* must exit here */
2348 /* port MESSAGE_TIMEOUT */
2349 void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type, union parameter *param)
2353 trace_header("TIMEOUT", DIRECTION_IN);
2354 message_type = MESSAGE_DISCONNECT;
2355 switch (param->state)
2357 case PORT_STATE_OUT_SETUP:
2358 case PORT_STATE_OUT_OVERLAP:
2359 add_trace("state", NULL, "outgoing setup/dialing");
2361 /* no user responding */
2362 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2363 return; /* must exit here */
2365 case PORT_STATE_IN_SETUP:
2366 case PORT_STATE_IN_OVERLAP:
2367 add_trace("state", NULL, "incoming setup/dialing");
2368 param->disconnectinfo.cause = CAUSE_INVALID; /* number incomplete */
2369 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2372 case PORT_STATE_OUT_PROCEEDING:
2373 add_trace("state", NULL, "outgoing proceeding");
2375 param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
2376 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2377 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2378 return; /* must exit here */
2380 case PORT_STATE_IN_PROCEEDING:
2381 add_trace("state", NULL, "incoming proceeding");
2382 param->disconnectinfo.cause = CAUSE_NOUSER;
2383 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL; /* no user responding */
2386 case PORT_STATE_OUT_ALERTING:
2387 add_trace("state", NULL, "outgoing alerting");
2389 param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
2390 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2391 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2392 return; /* must exit here */
2394 case PORT_STATE_CONNECT:
2395 add_trace("state", NULL, "connect");
2397 param->disconnectinfo.cause = CAUSE_NORMAL; /* normal */
2398 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2399 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2400 return; /* must exit here */
2402 case PORT_STATE_IN_ALERTING:
2403 add_trace("state", NULL, "incoming alerting");
2404 param->disconnectinfo.cause = CAUSE_NOANSWER;
2405 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2408 case PORT_STATE_IN_DISCONNECT:
2409 case PORT_STATE_OUT_DISCONNECT:
2410 add_trace("state", NULL, "disconnect");
2412 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
2413 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2414 return; /* must exit here */
2417 param->disconnectinfo.cause = 31; /* normal unspecified */
2418 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2421 /* release call, disconnect isdn */
2423 new_state(EPOINT_STATE_OUT_DISCONNECT);
2424 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2425 SCPY(e_tone, cause);
2428 set_tone(portlist, cause);
2429 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2430 portlist = portlist->next;
2432 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
2435 /* port MESSAGE_NOTIFY */
2436 void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, union parameter *param)
2438 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2440 struct lcr_msg *message;
2441 const char *logtext = "";
2444 /* signal to call tool */
2445 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);
2446 if (param->notifyinfo.notify)
2448 e_rx_state = track_notify(e_rx_state, param->notifyinfo.notify);
2451 /* if we get notification from stack, local shows if we disabled/enabled audio stream */
2452 if (param->notifyinfo.local) switch(param->notifyinfo.notify)
2454 case INFO_NOTIFY_REMOTE_HOLD:
2455 case INFO_NOTIFY_USER_SUSPENDED:
2456 /* tell call about it */
2457 if (ea_endpoint->ep_join_id)
2459 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2460 message->param.audiopath = 0;
2461 message_put(message);
2465 case INFO_NOTIFY_REMOTE_RETRIEVAL:
2466 case INFO_NOTIFY_USER_RESUMED:
2467 /* set volume of rx and tx */
2468 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
2469 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
2472 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2473 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2474 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
2475 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
2476 message_put(message);
2478 /* set current tone */
2480 set_tone(portlist, e_tone);
2481 /* tell call about it */
2482 if (ea_endpoint->ep_join_id)
2484 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2485 message->param.audiopath = 1;
2486 message_put(message);
2491 /* get name of notify */
2492 switch(param->notifyinfo.notify)
2498 logtext = "USER_SUSPENDED";
2501 logtext = "BEARER_SERVICE_CHANGED";
2504 logtext = "USER_RESUMED";
2507 logtext = "CONFERENCE_ESTABLISHED";
2510 logtext = "CONFERENCE_DISCONNECTED";
2513 logtext = "OTHER_PARTY_ADDED";
2516 logtext = "ISOLATED";
2519 logtext = "REATTACHED";
2522 logtext = "OTHER_PARTY_ISOLATED";
2525 logtext = "OTHER_PARTY_REATTACHED";
2528 logtext = "OTHER_PARTY_SPLIT";
2531 logtext = "OTHER_PARTY_DISCONNECTED";
2534 logtext = "CONFERENCE_FLOATING";
2537 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
2540 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
2543 logtext = "CALL_IS_A_WAITING_CALL";
2546 logtext = "DIVERSION_ACTIVATED";
2549 logtext = "RESERVED_CT_1";
2552 logtext = "RESERVED_CT_2";
2555 logtext = "REVERSE_CHARGING";
2558 logtext = "REMOTE_HOLD";
2561 logtext = "REMOTE_RETRIEVAL";
2564 logtext = "CALL_IS_DIVERTING";
2567 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
2572 /* notify call if available */
2573 if (ea_endpoint->ep_join_id)
2575 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOTIFY);
2576 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
2577 message_put(message);
2582 /* port MESSAGE_FACILITY */
2583 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
2585 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2587 struct lcr_msg *message;
2589 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_FACILITY);
2590 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2591 message_put(message);
2594 /* port MESSAGE_SUSPEND */
2595 /* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
2596 void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
2598 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2600 /* epoint is now parked */
2601 ea_endpoint->ep_park = 1;
2602 memcpy(ea_endpoint->ep_park_callid, param->parkinfo.callid, sizeof(ea_endpoint->ep_park_callid));
2603 ea_endpoint->ep_park_len = (param->parkinfo.len>8)?8:param->parkinfo.len;
2605 /* remove port relation */
2606 ea_endpoint->free_portlist(portlist);
2609 /* port MESSAGE_RESUME */
2610 /* NOTE: before resume, the active-notification must be done in order to set call mixer */
2611 void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
2613 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2615 /* epoint is now resumed */
2616 ea_endpoint->ep_park = 0;
2621 /* port sends message to the endpoint
2623 void EndpointAppPBX::ea_message_port(unsigned int port_id, int message_type, union parameter *param)
2625 struct port_list *portlist;
2627 portlist = ea_endpoint->ep_portlist;
2630 if (port_id == portlist->port_id)
2632 portlist = portlist->next;
2636 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);
2640 // PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
2641 switch(message_type)
2643 case MESSAGE_DATA: /* data from port */
2644 /* check if there is a call */
2645 if (!ea_endpoint->ep_join_id)
2647 /* continue if only one portlist */
2648 if (ea_endpoint->ep_portlist->next != NULL)
2650 /* forward message */
2651 message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2654 case MESSAGE_TONE_EOF: /* tone is end of file */
2655 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
2658 if (e_action->index == ACTION_VBOX_PLAY)
2662 if (e_action->index == ACTION_EFI)
2669 case MESSAGE_TONE_COUNTER: /* counter info received */
2670 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);
2672 if (e_action->index == ACTION_VBOX_PLAY)
2674 e_vbox_counter = param->counter.current;
2675 if (param->counter.max >= 0)
2676 e_vbox_counter_max = param->counter.max;
2680 /* PORT sends SETUP message */
2682 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);
2683 if (e_state!=EPOINT_STATE_IDLE)
2685 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
2688 port_setup(portlist, message_type, param);
2691 /* PORT sends INFORMATION message */
2692 case MESSAGE_INFORMATION: /* additional digits received */
2693 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);
2694 port_information(portlist, message_type, param);
2697 /* PORT sends FACILITY message */
2698 case MESSAGE_FACILITY:
2699 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2700 port_facility(portlist, message_type, param);
2703 /* PORT sends DTMF message */
2704 case MESSAGE_DTMF: /* dtmf digits received */
2705 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);
2706 port_dtmf(portlist, message_type, param);
2709 /* PORT sends CRYPT message */
2710 case MESSAGE_CRYPT: /* crypt response received */
2711 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) crypt response=%d\n", ea_endpoint->ep_serial, param->crypt.type);
2712 port_crypt(portlist, message_type, param);
2715 /* PORT sends MORE message */
2716 case MESSAGE_OVERLAP:
2717 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);
2718 if (e_state != EPOINT_STATE_OUT_SETUP)
2720 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);
2723 port_overlap(portlist, message_type, param);
2726 /* PORT sends PROCEEDING message */
2727 case MESSAGE_PROCEEDING: /* port is proceeding */
2728 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);
2729 if (e_state!=EPOINT_STATE_OUT_SETUP
2730 && e_state!=EPOINT_STATE_OUT_OVERLAP)
2732 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);
2735 port_proceeding(portlist, message_type, param);
2738 /* PORT sends ALERTING message */
2739 case MESSAGE_ALERTING:
2740 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);
2741 if (e_state!=EPOINT_STATE_OUT_SETUP
2742 && e_state!=EPOINT_STATE_OUT_OVERLAP
2743 && e_state!=EPOINT_STATE_OUT_PROCEEDING)
2745 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);
2748 port_alerting(portlist, message_type, param);
2751 /* PORT sends CONNECT message */
2752 case MESSAGE_CONNECT:
2753 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);
2754 if (e_state!=EPOINT_STATE_OUT_SETUP
2755 && e_state!=EPOINT_STATE_OUT_OVERLAP
2756 && e_state!=EPOINT_STATE_OUT_PROCEEDING
2757 && e_state!=EPOINT_STATE_OUT_ALERTING)
2759 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
2762 port_connect(portlist, message_type, param);
2765 /* PORT sends DISCONNECT message */
2766 case MESSAGE_DISCONNECT: /* port is disconnected */
2767 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);
2768 port_disconnect_release(portlist, message_type, param);
2771 /* PORT sends a RELEASE message */
2772 case MESSAGE_RELEASE: /* port releases */
2773 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);
2774 /* portlist is release at port_disconnect_release, thanx Paul */
2775 port_disconnect_release(portlist, message_type, param);
2778 /* PORT sends a TIMEOUT message */
2779 case MESSAGE_TIMEOUT:
2780 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);
2781 port_timeout(portlist, message_type, param);
2782 break; /* release */
2784 /* PORT sends a NOTIFY message */
2785 case MESSAGE_NOTIFY:
2786 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);
2787 port_notify(portlist, message_type, param);
2790 /* PORT sends a SUSPEND message */
2791 case MESSAGE_SUSPEND:
2792 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);
2793 port_suspend(portlist, message_type, param);
2794 break; /* suspend */
2796 /* PORT sends a RESUME message */
2797 case MESSAGE_RESUME:
2798 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);
2799 port_resume(portlist, message_type, param);
2803 kann nach dem test gelöscht werden, da eine direkte funktion im join und im mISDN zum austausch der message existiert
2804 /* port assigns bchannel */
2805 case MESSAGE_BCHANNEL: /* bchannel assignment messafe */
2806 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);
2807 /* only one port is expected to be connected to bchannel */
2808 message = message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2809 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_IN);
2815 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received a wrong message: %d\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, message_type);
2818 /* Note: this endpoint may be destroyed, so we MUST return */
2822 /* messages from join
2824 /* join MESSAGE_CRYPT */
2825 void EndpointAppPBX::join_crypt(struct port_list *portlist, int message_type, union parameter *param)
2827 switch(param->crypt.type)
2829 /* message from remote port to "crypt manager" */
2830 case CU_ACTK_REQ: /* activate key-exchange */
2831 case CU_ACTS_REQ: /* activate shared key */
2832 case CU_DACT_REQ: /* deactivate */
2833 case CU_INFO_REQ: /* request last info message */
2834 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2837 /* message from "crypt manager" to user */
2838 case CU_ACTK_CONF: /* key-echange done */
2839 case CU_ACTS_CONF: /* shared key done */
2840 case CU_DACT_CONF: /* deactivated */
2841 case CU_DACT_IND: /* deactivated */
2842 case CU_ERROR_IND: /* receive error message */
2843 case CU_INFO_IND: /* receive info message */
2844 case CU_INFO_CONF: /* receive info message */
2845 encrypt_result(param->crypt.type, (char *)param->crypt.data);
2849 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);
2853 /* join MESSAGE_INFORMATION */
2854 void EndpointAppPBX::join_information(struct port_list *portlist, int message_type, union parameter *param)
2856 struct lcr_msg *message;
2862 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2863 memcpy(&message->param.information, ¶m->information, sizeof(struct dialing_info));
2864 message_put(message);
2865 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2866 portlist = portlist->next;
2870 /* join MESSAGE_FACILITY */
2871 void EndpointAppPBX::join_facility(struct port_list *portlist, int message_type, union parameter *param)
2873 struct lcr_msg *message;
2875 if (!e_ext.facility && e_ext.number[0])
2882 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_FACILITY);
2883 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2884 message_put(message);
2885 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2886 portlist = portlist->next;
2890 /* join MESSAGE_MORE */
2891 void EndpointAppPBX::join_overlap(struct port_list *portlist, int message_type, union parameter *param)
2893 struct lcr_msg *message;
2895 new_state(EPOINT_STATE_IN_OVERLAP);
2898 if (e_join_pattern && e_ext.own_setup)
2900 /* disconnect audio */
2901 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2902 message->param.audiopath = 0;
2903 message_put(message);
2905 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
2907 if (e_dialinginfo.id[0])
2908 set_tone(portlist, "dialing");
2910 set_tone(portlist, "dialtone");
2913 if (e_dialinginfo.id[0])
2915 set_tone(portlist, "dialing");
2918 if (e_ext.number[0])
2919 set_tone(portlist, "dialpbx");
2921 set_tone(portlist, "dialtone");
2925 /* join MESSAGE_PROCEEDING */
2926 void EndpointAppPBX::join_proceeding(struct port_list *portlist, int message_type, union parameter *param)
2928 struct lcr_msg *message;
2930 new_state(EPOINT_STATE_IN_PROCEEDING);
2932 /* own proceeding tone */
2935 /* connect / disconnect audio */
2936 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2937 if (e_ext.own_proceeding)
2938 message->param.audiopath = 0;
2940 message->param.audiopath = 1;
2941 message_put(message);
2943 // UCPY(e_join_tone, "proceeding");
2946 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
2947 message_put(message);
2948 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2950 set_tone(portlist, "proceeding");
2953 /* join MESSAGE_ALERTING */
2954 void EndpointAppPBX::join_alerting(struct port_list *portlist, int message_type, union parameter *param)
2956 struct lcr_msg *message;
2958 new_state(EPOINT_STATE_IN_ALERTING);
2960 /* own alerting tone */
2963 /* connect / disconnect audio */
2964 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2965 if (e_ext.own_alerting)
2966 message->param.audiopath = 0;
2968 message->param.audiopath = 1;
2969 message_put(message);
2973 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
2974 message_put(message);
2975 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2977 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
2979 set_tone(portlist, "ringing");
2982 if (e_ext.number[0])
2983 set_tone(portlist, "ringpbx");
2985 set_tone(portlist, "ringing");
2988 /* join MESSAGE_CONNECT */
2989 void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type, union parameter *param)
2991 struct lcr_msg *message;
2993 new_state(EPOINT_STATE_CONNECT);
2994 // UCPY(e_join_tone, "");
2996 if (e_ext.number[0])
2997 e_dtmf = 1; /* allow dtmf */
3000 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_callerinfo));
3003 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3004 memcpy(&message->param, param, sizeof(union parameter));
3006 /* screen clip if prefix is required */
3007 if (e_ext.number[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0])
3009 SCPY(message->param.connectinfo.id, e_ext.clip_prefix);
3010 SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype, options.national, options.international));
3011 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
3014 /* use internal caller id */
3015 if (e_ext.number[0] && e_connectinfo.extension[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
3017 SCPY(message->param.connectinfo.id, e_connectinfo.extension);
3018 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
3021 /* handle restricted caller ids */
3022 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);
3023 /* display callerid if desired for extension */
3024 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));
3026 /* use conp, if enabld */
3027 // if (!e_ext.centrex)
3028 // message->param.connectinfo.name[0] = '\0';
3031 message_put(message);
3032 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3034 set_tone(portlist, NULL);
3036 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3037 message->param.audiopath = 1;
3038 message_put(message);
3042 /* join MESSAGE_DISCONNECT MESSAGE_RELEASE */
3043 void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *param)
3046 struct lcr_msg *message;
3047 struct port_list *portlist = NULL;
3050 /* be sure that we are active */
3052 e_tx_state = NOTIFY_STATE_ACTIVE;
3054 /* we are powerdialing, if e_powerdialing is set and limit is not exceeded if given */
3055 if (e_powerdialing && ((e_powercount+1)<e_powerlimit || e_powerlimit<1))
3057 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
3059 /* set time for power dialing */
3060 e_powerdialing = now_d + e_powerdelay; /* set redial in the future */
3063 /* set redial tone */
3064 if (ea_endpoint->ep_portlist)
3068 set_tone(ea_endpoint->ep_portlist, "redial");
3069 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);
3070 /* send proceeding when powerdialing and still setup (avoid dialing timeout) */
3071 if (e_state==EPOINT_STATE_IN_OVERLAP)
3073 new_state(EPOINT_STATE_IN_PROCEEDING);
3074 if (ea_endpoint->ep_portlist)
3076 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3077 message_put(message);
3078 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3080 /* caused the error, that the first knock sound was not there */
3081 /* set_tone(portlist, "proceeding"); */
3083 /* send display of powerdialing */
3084 if (e_ext.display_dialing)
3086 portlist = ea_endpoint->ep_portlist;
3089 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3091 SPRINT(message->param.notifyinfo.display, "Retry %d of %d", e_powercount, e_powerlimit);
3093 SPRINT(message->param.notifyinfo.display, "Retry %d", e_powercount);
3094 message_put(message);
3095 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3096 portlist = portlist->next;
3105 if ((e_state!=EPOINT_STATE_CONNECT
3106 && e_state!=EPOINT_STATE_OUT_DISCONNECT
3107 && e_state!=EPOINT_STATE_IN_OVERLAP
3108 && e_state!=EPOINT_STATE_IN_PROCEEDING
3109 && e_state!=EPOINT_STATE_IN_ALERTING)
3110 || !ea_endpoint->ep_portlist) /* or no port */
3112 process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
3113 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause); /* RELEASE_TYPE, join, port */
3114 return; /* must exit here */
3119 e_join_cause = param->disconnectinfo.cause;
3120 e_join_location = param->disconnectinfo.location;
3123 /* on release we need the audio again! */
3124 if (message_type == MESSAGE_RELEASE)
3127 ea_endpoint->ep_join_id = 0;
3129 /* disconnect and select tone */
3130 new_state(EPOINT_STATE_OUT_DISCONNECT);
3131 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
3132 /* if own_cause, we must release the join */
3133 if (e_ext.own_cause /* own cause */
3134 || !e_join_pattern) /* no patterns */
3136 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);
3137 if (message_type != MESSAGE_RELEASE)
3138 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
3140 } else /* else we enable audio */
3142 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3143 message->param.audiopath = 1;
3144 message_put(message);
3146 /* send disconnect message */
3147 SCPY(e_tone, cause);
3148 portlist = ea_endpoint->ep_portlist;
3151 set_tone(portlist, cause);
3152 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
3153 portlist = portlist->next;
3157 /* join MESSAGE_SETUP */
3158 void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, union parameter *param)
3160 struct lcr_msg *message;
3161 // struct interface *interface;
3163 /* if we already in setup state, we just update the dialing with new digits */
3164 if (e_state == EPOINT_STATE_OUT_SETUP
3165 || e_state == EPOINT_STATE_OUT_OVERLAP)
3167 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we are in setup state, so we do overlap dialing.\n", ea_endpoint->ep_serial);
3168 /* if digits changed, what we have already dialed */
3169 if (!!strncmp(e_dialinginfo.id,param->setup.dialinginfo.id,strlen(e_dialinginfo.id)))
3171 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);
3172 /* release all ports */
3173 while((portlist = ea_endpoint->ep_portlist))
3175 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
3176 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
3177 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3178 message_put(message);
3179 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3180 ea_endpoint->free_portlist(portlist);
3183 /* disconnect audio */
3184 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3185 message->param.audiopath = 0;
3186 message_put(message);
3188 /* get dialing info */
3189 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3190 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3191 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3192 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3193 new_state(EPOINT_STATE_OUT_OVERLAP);
3196 e_redial = now_d + 1; /* set redial one second in the future */
3199 /* if we have a pending redial, so we just adjust the dialing number */
3202 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);
3203 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3206 if (!ea_endpoint->ep_portlist)
3208 PERROR("ERROR: overlap dialing to a NULL port relation\n");
3210 if (ea_endpoint->ep_portlist->next)
3212 PERROR("ERROR: overlap dialing to a port_list port relation\n");
3214 if (e_state == EPOINT_STATE_OUT_SETUP)
3217 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);
3218 SCAT(e_dialing_queue, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3222 /* get what we have not dialed yet */
3223 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));
3224 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
3225 SCPY(message->param.information.id, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3226 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
3227 message_put(message);
3228 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3230 /* always store what we have dialed or queued */
3231 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3235 if (e_state != EPOINT_STATE_IDLE)
3237 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
3240 /* if an internal extension is dialed, copy that number */
3241 if (param->setup.dialinginfo.itype==INFO_ITYPE_ISDN_EXTENSION || param->setup.dialinginfo.itype==INFO_ITYPE_VBOX)
3242 SCPY(e_ext.number, param->setup.dialinginfo.id);
3243 /* if an internal extension is dialed, get extension's info about caller */
3244 if (e_ext.number[0])
3246 if (!read_extension(&e_ext, e_ext.number))
3248 e_ext.number[0] = '\0';
3249 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the called terminal='%s' is not found in directory tree!\n", ea_endpoint->ep_serial, e_ext.number);
3253 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3254 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3255 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3256 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3258 /* process (voice over) data calls */
3259 if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO)
3261 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) handling data call as audio call: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
3262 memset(&e_capainfo, 0, sizeof(e_capainfo));
3263 e_capainfo.bearer_capa = INFO_BC_AUDIO;
3264 e_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
3265 e_capainfo.bearer_info1 = (options.law=='u')?INFO_INFO1_ULAW:INFO_INFO1_ALAW;
3268 new_state(EPOINT_STATE_OUT_SETUP);
3269 /* call special setup routine */
3273 /* join MESSAGE_mISDNSIGNAL */
3274 void EndpointAppPBX::join_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param)
3276 struct lcr_msg *message;
3280 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
3281 memcpy(&message->param, param, sizeof(union parameter));
3282 message_put(message);
3283 portlist = portlist->next;
3287 /* join MESSAGE_NOTIFY */
3288 void EndpointAppPBX::join_notify(struct port_list *portlist, int message_type, union parameter *param)
3290 struct lcr_msg *message;
3293 if (param->notifyinfo.notify)
3295 new_state = track_notify(e_tx_state, param->notifyinfo.notify);
3296 // /* if notification was generated locally, we turn hold music on/off */
3297 // if (param->notifyinfo.local)
3298 // 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)
3303 if (new_state!=NOTIFY_STATE_HOLD && new_state!=NOTIFY_STATE_SUSPEND)
3305 if (!strcmp(e_tone, "hold")) // don't interrupt other tones
3309 set_tone(portlist, "");
3310 portlist = portlist->next;
3313 portlist = ea_endpoint->ep_portlist;
3318 if (new_state==NOTIFY_STATE_HOLD || new_state==NOTIFY_STATE_SUSPEND)
3322 set_tone(portlist, "hold");
3323 portlist = portlist->next;
3325 portlist = ea_endpoint->ep_portlist;
3330 /* save new state */
3331 e_tx_state = new_state;
3334 /* notify port(s) about it */
3337 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3338 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
3339 /* handle restricted caller ids */
3340 apply_callerid_restriction(&e_ext, message->param.notifyinfo.id, &message->param.notifyinfo.ntype, &message->param.notifyinfo.present, 0, message->param.notifyinfo.extension, NULL);
3341 /* display callerid if desired for extension */
3342 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));
3343 message_put(message);
3344 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3345 portlist = portlist->next;
3349 /* JOIN sends messages to the endpoint
3351 void EndpointAppPBX::ea_message_join(unsigned int join_id, int message_type, union parameter *param)
3353 struct port_list *portlist;
3354 struct lcr_msg *message;
3358 PERROR("EPOINT(%d) error: JOIN == NULL.\n", ea_endpoint->ep_serial);
3362 portlist = ea_endpoint->ep_portlist;
3364 /* send MESSAGE_DATA to port */
3365 if (message_type == MESSAGE_DATA)
3367 if (join_id == ea_endpoint->ep_join_id) // still linked with JOIN
3369 /* skip if no port relation */
3372 /* skip if more than one port relation */
3375 /* forward audio data to port */
3376 message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3381 // 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);
3382 switch(message_type)
3384 /* JOIN SENDS TONE message */
3386 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);
3387 set_tone(portlist, param->tone.name);
3390 /* JOIN SENDS CRYPT message */
3392 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);
3393 join_crypt(portlist, message_type, param);
3396 /* JOIN sends INFORMATION message */
3397 case MESSAGE_INFORMATION:
3398 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);
3399 join_information(portlist, message_type, param);
3402 /* JOIN sends FACILITY message */
3403 case MESSAGE_FACILITY:
3404 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);
3405 join_facility(portlist, message_type, param);
3408 /* JOIN sends OVERLAP message */
3409 case MESSAGE_OVERLAP:
3410 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);
3411 if (e_state!=EPOINT_STATE_IN_SETUP
3412 && e_state!=EPOINT_STATE_IN_OVERLAP)
3414 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3417 join_overlap(portlist, message_type, param);
3420 /* JOIN sends PROCEEDING message */
3421 case MESSAGE_PROCEEDING:
3422 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);
3423 if(e_state!=EPOINT_STATE_IN_OVERLAP)
3425 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3428 join_proceeding(portlist, message_type, param);
3431 /* JOIN sends ALERTING message */
3432 case MESSAGE_ALERTING:
3433 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);
3434 if (e_state!=EPOINT_STATE_IN_OVERLAP
3435 && e_state!=EPOINT_STATE_IN_PROCEEDING)
3437 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state.\n", ea_endpoint->ep_serial);
3440 join_alerting(portlist, message_type, param);
3443 /* JOIN sends CONNECT message */
3444 case MESSAGE_CONNECT:
3445 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);
3446 if (e_state!=EPOINT_STATE_IN_OVERLAP
3447 && e_state!=EPOINT_STATE_IN_PROCEEDING
3448 && e_state!=EPOINT_STATE_IN_ALERTING)
3450 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
3453 join_connect(portlist, message_type, param);
3456 /* JOIN sends DISCONNECT/RELEASE message */
3457 case MESSAGE_DISCONNECT: /* JOIN disconnect */
3458 case MESSAGE_RELEASE: /* JOIN releases */
3459 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);
3460 join_disconnect_release(message_type, param);
3463 /* JOIN sends SETUP message */
3465 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);
3466 join_setup(portlist, message_type, param);
3469 /* JOIN sends special mISDNSIGNAL message */
3470 case MESSAGE_mISDNSIGNAL: /* isdn message to port */
3471 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);
3472 join_mISDNsignal(portlist, message_type, param);
3476 kann nach dem test gelöscht werden, da eine direkte funktion im join und im mISDN zum austausch der message existiert
3477 /* JOIN requests bchannel */
3478 case MESSAGE_BCHANNEL: /* indicates the need of own bchannel access */
3479 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);
3480 /* only one port is expected to be connected to bchannel */
3487 set_tone(portlist, NULL);
3488 message = message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3489 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3493 /* JOIN has pattern available */
3494 case MESSAGE_PATTERN: /* indicating pattern available */
3495 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);
3496 if (!e_join_pattern)
3498 PDEBUG(DEBUG_EPOINT, "-> pattern becomes available\n");
3503 set_tone(portlist, NULL);
3504 portlist = portlist->next;
3506 /* connect our audio tx and rx (blueboxing should be possibe before connect :)*/
3507 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3508 message->param.audiopath = 1;
3509 message_put(message);
3513 /* JOIN has no pattern available */
3514 case MESSAGE_NOPATTERN: /* indicating no pattern available */
3515 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);
3518 PDEBUG(DEBUG_EPOINT, "-> pattern becomes unavailable\n");
3520 /* disconnect our audio tx and rx */
3521 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3522 message->param.audiopath = 0;
3523 message_put(message);
3528 /* JOIN (dunno at the moment) */
3529 case MESSAGE_REMOTE_AUDIO:
3530 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);
3531 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3532 message->param.audiopath = param->channel;
3533 message_put(message);
3537 /* JOIN sends a notify message */
3538 case MESSAGE_NOTIFY:
3539 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);
3540 join_notify(portlist, message_type, param);
3543 /* JOIN wants keypad / dtml */
3544 case MESSAGE_ENABLEKEYPAD:
3545 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);
3548 trace_header("ENABLE KEYPAD", DIRECTION_NONE);
3553 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received a wrong message: #%d\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, message_type);
3558 /* pick_join will connect the first incoming call found. the endpoint
3559 * will receivce a MESSAGE_CONNECT.
3561 int match_list(char *list, char *item)
3563 char *end, *next = NULL;
3565 /* no list make matching */
3571 /* eliminate white spaces */
3572 while (*list <= ' ')
3579 /* if end of list is reached, we return */
3580 if (list[0] == '\0')
3582 /* if we have more than one entry (left) */
3583 if ((end = strchr(list, ',')))
3586 next = end = strchr(list, '\0');
3587 while (*(end-1) <= ' ')
3589 /* if string part matches item */
3590 if (!strncmp(list, item, end-list))
3596 void EndpointAppPBX::pick_join(char *extensions)
3598 struct lcr_msg *message;
3599 struct port_list *portlist;
3601 class EndpointAppPBX *eapp, *found;
3603 class JoinPBX *joinpbx;
3604 struct join_relation *relation;
3607 /* find an endpoint that is ringing internally or vbox with higher priority */
3610 eapp = apppbx_first;
3613 if (eapp!=this && ea_endpoint->ep_portlist)
3615 portlist = eapp->ea_endpoint->ep_portlist;
3618 if ((port = find_port_id(portlist->port_id)))
3620 if (port->p_type == PORT_TYPE_VBOX_OUT)
3622 if (match_list(extensions, eapp->e_ext.number))
3629 if ((port->p_type==PORT_TYPE_DSS1_NT_OUT || port->p_type==PORT_TYPE_DSS1_TE_OUT)
3630 && port->p_state==PORT_STATE_OUT_ALERTING)
3631 if (match_list(extensions, eapp->e_ext.number))
3636 portlist = portlist->next;
3644 /* if no endpoint found */
3647 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);
3649 set_tone(ea_endpoint->ep_portlist, "cause_10");
3650 message_disconnect_port(ea_endpoint->ep_portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
3651 new_state(EPOINT_STATE_OUT_DISCONNECT);
3656 if (ea_endpoint->ep_join_id)
3658 PERROR("EPOINT(%d) we already have a join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3661 if (!eapp->ea_endpoint->ep_join_id)
3663 PERROR("EPOINT(%d) ringing endpoint has no join.\n", ea_endpoint->ep_serial);
3666 join = find_join_id(eapp->ea_endpoint->ep_join_id);
3669 PERROR("EPOINT(%d) ringing endpoint's join not found.\n", ea_endpoint->ep_serial);
3672 if (join->j_type != JOIN_TYPE_PBX)
3674 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ringing endpoint's join is not a PBX join, so we must reject.\n", ea_endpoint->ep_serial);
3677 joinpbx = (class JoinPBX *)join;
3678 relation = joinpbx->j_relation;
3681 PERROR("EPOINT(%d) ringing endpoint's join has no relation. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3684 while (relation->epoint_id != eapp->ea_endpoint->ep_serial)
3686 relation = relation->next;
3689 PERROR("EPOINT(%d) ringing endpoint's join has no relation to that join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3694 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found ringing endpoint: %d.\n", ea_endpoint->ep_serial, eapp->ea_endpoint->ep_serial);
3696 if (options.deb & DEBUG_EPOINT)
3698 class Join *debug_c = join_first;
3699 class Endpoint *debug_e = epoint_first;
3700 class Port *debug_p = port_first;
3702 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(before)");
3704 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3707 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3708 debug_c = debug_c->next;
3710 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3713 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3714 debug_e = debug_e->next;
3716 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3719 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld (active)\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3720 debug_p = debug_p->next;
3725 ea_endpoint->ep_join_id = eapp->ea_endpoint->ep_join_id; /* we get the join */
3726 relation->epoint_id = ea_endpoint->ep_serial; /* the join gets us */
3727 eapp->ea_endpoint->ep_join_id = 0; /* the ringing endpoint will get disconnected */
3729 /* connnecting our endpoint */
3730 new_state(EPOINT_STATE_CONNECT);
3731 if (e_ext.number[0])
3733 set_tone(ea_endpoint->ep_portlist, NULL);
3735 /* now we send a release to the ringing endpoint */
3736 message = message_create(ea_endpoint->ep_join_id, eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3737 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
3738 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3739 message_put(message);
3741 /* we send a connect to the join with our caller id */
3742 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CONNECT);
3743 SCPY(message->param.connectinfo.id, e_callerinfo.id);
3744 message->param.connectinfo.present = e_callerinfo.present;
3745 message->param.connectinfo.screen = e_callerinfo.screen;
3746 message->param.connectinfo.itype = e_callerinfo.itype;
3747 message->param.connectinfo.ntype = e_callerinfo.ntype;
3748 message_put(message);
3750 /* we send a connect to our port with the remote callerid */
3751 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3752 SCPY(message->param.connectinfo.id, eapp->e_callerinfo.id);
3753 message->param.connectinfo.present = eapp->e_callerinfo.present;
3754 message->param.connectinfo.screen = eapp->e_callerinfo.screen;
3755 message->param.connectinfo.itype = eapp->e_callerinfo.itype;
3756 message->param.connectinfo.ntype = eapp->e_callerinfo.ntype;
3757 /* handle restricted caller ids */
3758 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);
3759 /* display callerid if desired for extension */
3760 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));
3761 message_put(message);
3763 /* we send a connect to the audio path (not for vbox) */
3764 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3765 message->param.audiopath = 1;
3766 message_put(message);
3768 /* beeing paranoid, we make call update */
3769 joinpbx->j_updatebridge = 1;
3771 if (options.deb & DEBUG_EPOINT)
3773 class Join *debug_c = join_first;
3774 class Endpoint *debug_e = epoint_first;
3775 class Port *debug_p = port_first;
3777 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(after)");
3779 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3782 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3783 debug_c = debug_c->next;
3785 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3788 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3789 debug_e = debug_e->next;
3791 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3794 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3795 debug_p = debug_p->next;
3801 /* join calls (look for a join that is on hold (same isdn interface/terminal))
3803 void EndpointAppPBX::join_join(void)
3805 struct lcr_msg *message;
3806 struct join_relation *our_relation, *other_relation;
3807 struct join_relation **our_relation_pointer, **other_relation_pointer;
3808 class Join *our_join, *other_join;
3809 class JoinPBX *our_joinpbx, *other_joinpbx;
3810 class EndpointAppPBX *other_eapp; class Endpoint *temp_epoint;
3811 class Port *our_port, *other_port;
3812 class Pdss1 *our_pdss1, *other_pdss1;
3814 /* are we a candidate to join a join */
3815 our_join = find_join_id(ea_endpoint->ep_join_id);
3818 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3821 if (our_join->j_type != JOIN_TYPE_PBX)
3823 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: join is not a pbx join.\n", ea_endpoint->ep_serial);
3826 our_joinpbx = (class JoinPBX *)our_join;
3827 if (!ea_endpoint->ep_portlist)
3829 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
3832 if (!e_ext.number[0])
3834 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
3837 our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
3840 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
3843 if ((our_port->p_type&PORT_CLASS_mISDN_MASK) != PORT_CLASS_mISDN_DSS1)
3845 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not isdn.\n", ea_endpoint->ep_serial);
3848 our_pdss1 = (class Pdss1 *)our_port;
3850 /* find an endpoint that is on hold and has the same mISDNport that we are on */
3851 other_eapp = apppbx_first;
3854 if (other_eapp == this)
3856 other_eapp = other_eapp->next;
3859 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);
3860 if (other_eapp->e_ext.number[0] /* has terminal */
3861 && other_eapp->ea_endpoint->ep_portlist /* has port */
3862 && other_eapp->ea_endpoint->ep_join_id) /* has join */
3864 other_port = find_port_id(other_eapp->ea_endpoint->ep_portlist->port_id);
3865 if (other_port) /* port still exists */
3867 if (other_port->p_type==PORT_TYPE_DSS1_NT_OUT
3868 || other_port->p_type==PORT_TYPE_DSS1_NT_IN) /* port is isdn nt-mode */
3870 other_pdss1 = (class Pdss1 *)other_port;
3871 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);
3872 if (other_pdss1->p_m_hold /* port is on hold */
3873 && other_pdss1->p_m_mISDNport == our_pdss1->p_m_mISDNport /* same isdn interface */
3874 && other_pdss1->p_m_d_ces == our_pdss1->p_m_d_ces) /* same tei+sapi */
3878 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of other type!\n", ea_endpoint->ep_serial);
3882 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port doesn't exist enymore.\n", ea_endpoint->ep_serial);
3885 other_eapp = other_eapp->next;
3889 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn interface with port on hold.\n", ea_endpoint->ep_serial);
3892 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port on hold found.\n", ea_endpoint->ep_serial);
3894 /* if we have the same join */
3895 if (other_eapp->ea_endpoint->ep_join_id == ea_endpoint->ep_join_id)
3897 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we an the other have the same join.\n", ea_endpoint->ep_serial);
3900 other_join = find_join_id(other_eapp->ea_endpoint->ep_join_id);
3903 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3906 if (other_join->j_type != JOIN_TYPE_PBX)
3908 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join is not a pbx join.\n", ea_endpoint->ep_serial);
3911 other_joinpbx = (class JoinPBX *)other_join;
3912 if (our_joinpbx->j_partyline && other_joinpbx->j_partyline)
3914 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both joins are partylines.\n", ea_endpoint->ep_serial);
3918 /* remove relation to endpoint for join on hold */
3919 other_relation = other_joinpbx->j_relation;
3920 other_relation_pointer = &other_joinpbx->j_relation;
3921 while(other_relation)
3923 if (other_relation->epoint_id == other_eapp->ea_endpoint->ep_serial)
3925 /* detach other endpoint on hold */
3926 *other_relation_pointer = other_relation->next;
3927 FREE(other_relation, sizeof(struct join_relation));
3929 other_relation = *other_relation_pointer;
3930 other_eapp->ea_endpoint->ep_join_id = 0;
3934 /* change join/hold pointer of endpoint to the new join */
3935 temp_epoint = find_epoint_id(other_relation->epoint_id);
3938 if (temp_epoint->ep_join_id == other_join->j_serial)
3939 temp_epoint->ep_join_id = our_join->j_serial;
3942 other_relation_pointer = &other_relation->next;
3943 other_relation = other_relation->next;
3945 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint on hold removed, other enpoints on join relinked (to our join).\n", ea_endpoint->ep_serial);
3947 /* join call relations */
3948 our_relation = our_joinpbx->j_relation;
3949 our_relation_pointer = &our_joinpbx->j_relation;
3952 our_relation_pointer = &our_relation->next;
3953 our_relation = our_relation->next;
3955 *our_relation_pointer = other_joinpbx->j_relation;
3956 other_joinpbx->j_relation = NULL;
3957 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) relations joined.\n", ea_endpoint->ep_serial);
3959 /* release endpoint on hold */
3960 message = message_create(other_joinpbx->j_serial, other_eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3961 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */
3962 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3963 message_put(message);
3965 /* if we are not a partyline, we get partyline state from other join */
3966 our_joinpbx->j_partyline += other_joinpbx->j_partyline;
3968 /* remove empty join */
3970 PDEBUG(DEBUG_EPOINT, "EPOINT(%d)d-join completely removed!\n");
3972 /* mixer must update */
3973 our_joinpbx->j_updatebridge = 1; /* update mixer flag */
3975 /* we send a retrieve to that endpoint */
3976 // mixer will update the hold-state of the join and send it to the endpoints is changes
3980 /* check if we have an external call
3981 * this is used to check for encryption ability
3983 int EndpointAppPBX::check_external(const char **errstr, class Port **port)
3985 struct join_relation *relation;
3987 class JoinPBX *joinpbx;
3988 class Endpoint *epoint;
3990 /* some paranoia check */
3991 if (!ea_endpoint->ep_portlist)
3993 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we have no port.\n", ea_endpoint->ep_serial);
3994 *errstr = "No Call";
3997 if (!e_ext.number[0])
3999 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we are not internal extension.\n", ea_endpoint->ep_serial);
4000 *errstr = "No Call";
4004 /* check if we have a join with 2 parties */
4005 join = find_join_id(ea_endpoint->ep_join_id);
4008 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have currently no join.\n", ea_endpoint->ep_serial);
4009 *errstr = "No Call";
4012 if (join->j_type != JOIN_TYPE_PBX)
4014 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join is not a pbx join.\n", ea_endpoint->ep_serial);
4015 *errstr = "No PBX Call";
4018 joinpbx = (class JoinPBX *)join;
4019 relation = joinpbx->j_relation;
4022 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no relation.\n", ea_endpoint->ep_serial);
4023 *errstr = "No Call";
4026 if (!relation->next)
4028 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd relation.\n", ea_endpoint->ep_serial);
4029 *errstr = "No Call";
4032 if (relation->next->next)
4034 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has more than two relations.\n", ea_endpoint->ep_serial);
4035 *errstr = "Err: Conference";
4038 if (relation->epoint_id == ea_endpoint->ep_serial)
4040 relation = relation->next;
4041 if (relation->epoint_id == ea_endpoint->ep_serial)
4043 PERROR("EPOINT(%d) SOFTWARE ERROR: both join relations are related to our endpoint.\n", ea_endpoint->ep_serial);
4044 *errstr = "Software Error";
4049 /* check remote port for external call */
4050 epoint = find_epoint_id(relation->epoint_id);
4053 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd endpoint.\n", ea_endpoint->ep_serial);
4054 *errstr = "No Call";
4057 if (!epoint->ep_portlist)
4059 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not port.\n", ea_endpoint->ep_serial);
4060 *errstr = "No Call";
4063 *port = find_port_id(epoint->ep_portlist->port_id);
4066 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has an none existing port.\n", ea_endpoint->ep_serial);
4067 *errstr = "No Call";
4070 if (((*port)->p_type&PORT_CLASS_mISDN_MASK)!=PORT_CLASS_mISDN_DSS1) /* port is not external isdn */
4072 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not an external port.\n", ea_endpoint->ep_serial);
4073 *errstr = "No Ext Call";
4076 if ((*port)->p_state != PORT_STATE_CONNECT)
4078 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint's port is not in connected state.\n", ea_endpoint->ep_serial);
4079 *errstr = "No Ext Connect";
4085 void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsigned int port_id, int dir)
4087 const char *logtext = "unknown";
4090 switch(message_type)
4093 trace_header("SETUP", dir);
4094 if (dir == DIRECTION_OUT)
4095 add_trace("to", NULL, "CH(%lu)", port_id);
4096 if (dir == DIRECTION_IN)
4097 add_trace("from", NULL, "CH(%lu)", port_id);
4098 if (param->setup.callerinfo.extension[0])
4099 add_trace("extension", NULL, "%s", param->setup.callerinfo.extension);
4100 add_trace("caller id", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype, options.national, options.international));
4101 switch(param->setup.callerinfo.present)
4103 case INFO_PRESENT_RESTRICTED:
4104 add_trace("caller id", "present", "restricted");
4106 case INFO_PRESENT_ALLOWED:
4107 add_trace("caller id", "present", "allowed");
4110 add_trace("caller id", "present", "not available");
4112 if (param->setup.callerinfo.ntype2)
4114 add_trace("caller id2", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id2, param->setup.callerinfo.ntype2, options.national, options.international));
4115 switch(param->setup.callerinfo.present)
4117 case INFO_PRESENT_RESTRICTED:
4118 add_trace("caller id2", "present", "restricted");
4120 case INFO_PRESENT_ALLOWED:
4121 add_trace("caller id2", "present", "allowed");
4124 add_trace("caller id2", "present", "not available");
4127 if (param->setup.redirinfo.id[0])
4129 add_trace("redir'ing", "number", "%s", numberrize_callerinfo(param->setup.redirinfo.id, param->setup.redirinfo.ntype, options.national, options.international));
4130 switch(param->setup.redirinfo.present)
4132 case INFO_PRESENT_RESTRICTED:
4133 add_trace("redir'ing", "present", "restricted");
4135 case INFO_PRESENT_ALLOWED:
4136 add_trace("redir'ing", "present", "allowed");
4139 add_trace("redir'ing", "present", "not available");
4142 if (param->setup.dialinginfo.id[0])
4143 add_trace("dialing", NULL, "%s", param->setup.dialinginfo.id);
4144 if (param->setup.dialinginfo.display[0])
4145 add_trace("display", NULL, "%s", param->setup.dialinginfo.display);
4146 if (param->setup.dialinginfo.sending_complete)
4147 add_trace("complete", NULL, "true", param->setup.dialinginfo.sending_complete);
4151 case MESSAGE_OVERLAP:
4152 trace_header("SETUP ACKNOWLEDGE", dir);
4153 if (dir == DIRECTION_OUT)
4154 add_trace("to", NULL, "CH(%lu)", port_id);
4155 if (dir == DIRECTION_IN)
4156 add_trace("from", NULL, "CH(%lu)", port_id);
4160 case MESSAGE_PROCEEDING:
4161 trace_header("PROCEEDING", dir);
4162 if (dir == DIRECTION_OUT)
4163 add_trace("to", NULL, "CH(%lu)", port_id);
4164 if (dir == DIRECTION_IN)
4165 add_trace("from", NULL, "CH(%lu)", port_id);
4169 case MESSAGE_ALERTING:
4170 trace_header("ALERTING", dir);
4171 if (dir == DIRECTION_OUT)
4172 add_trace("to", NULL, "CH(%lu)", port_id);
4173 if (dir == DIRECTION_IN)
4174 add_trace("from", NULL, "CH(%lu)", port_id);
4178 case MESSAGE_CONNECT:
4179 trace_header("CONNECT", dir);
4180 if (dir == DIRECTION_OUT)
4181 add_trace("to", NULL, "CH(%lu)", port_id);
4182 if (dir == DIRECTION_IN)
4183 add_trace("from", NULL, "CH(%lu)", port_id);
4184 if (param->connectinfo.extension[0])
4185 add_trace("extension", NULL, "%s", param->connectinfo.extension);
4186 add_trace("connect id", "number", "%s", numberrize_callerinfo(param->connectinfo.id, param->connectinfo.ntype, options.national, options.international));
4187 switch(param->connectinfo.present)
4189 case INFO_PRESENT_RESTRICTED:
4190 add_trace("connect id", "present", "restricted");
4192 case INFO_PRESENT_ALLOWED:
4193 add_trace("connect id", "present", "allowed");
4196 add_trace("connect id", "present", "not available");
4198 if (param->connectinfo.display[0])
4199 add_trace("display", NULL, "%s", param->connectinfo.display);
4203 case MESSAGE_DISCONNECT:
4204 case MESSAGE_RELEASE:
4205 if (message_type == MESSAGE_DISCONNECT)
4206 trace_header("DISCONNECT", dir);
4208 trace_header("RELEASE", dir);
4209 if (dir == DIRECTION_OUT)
4210 add_trace("to", NULL, "CH(%lu)", port_id);
4211 if (dir == DIRECTION_IN)
4212 add_trace("from", NULL, "CH(%lu)", port_id);
4213 add_trace("cause", "value", "%d", param->disconnectinfo.cause);
4214 switch(param->disconnectinfo.location)
4217 add_trace("cause", "location", "0-User");
4219 case LOCATION_PRIVATE_LOCAL:
4220 add_trace("cause", "location", "1-Local-PBX");
4222 case LOCATION_PUBLIC_LOCAL:
4223 add_trace("cause", "location", "2-Local-Exchange");
4225 case LOCATION_TRANSIT:
4226 add_trace("cause", "location", "3-Transit");
4228 case LOCATION_PUBLIC_REMOTE:
4229 add_trace("cause", "location", "4-Remote-Exchange");
4231 case LOCATION_PRIVATE_REMOTE:
4232 add_trace("cause", "location", "5-Remote-PBX");
4234 case LOCATION_INTERNATIONAL:
4235 add_trace("cause", "location", "7-International-Exchange");
4237 case LOCATION_BEYOND:
4238 add_trace("cause", "location", "10-Beyond-Interworking");
4241 add_trace("cause", "location", "%d", param->disconnectinfo.location);
4243 if (param->disconnectinfo.display[0])
4244 add_trace("display", NULL, "%s", param->disconnectinfo.display);
4248 case MESSAGE_NOTIFY:
4249 switch(param->notifyinfo.notify)
4255 logtext = "USER_SUSPENDED";
4258 logtext = "BEARER_SERVICE_CHANGED";
4261 logtext = "USER_RESUMED";
4264 logtext = "CONFERENCE_ESTABLISHED";
4267 logtext = "CONFERENCE_DISCONNECTED";
4270 logtext = "OTHER_PARTY_ADDED";
4273 logtext = "ISOLATED";
4276 logtext = "REATTACHED";
4279 logtext = "OTHER_PARTY_ISOLATED";
4282 logtext = "OTHER_PARTY_REATTACHED";
4285 logtext = "OTHER_PARTY_SPLIT";
4288 logtext = "OTHER_PARTY_DISCONNECTED";
4291 logtext = "CONFERENCE_FLOATING";
4294 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
4297 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
4300 logtext = "CALL_IS_A_WAITING_CALL";
4303 logtext = "DIVERSION_ACTIVATED";
4306 logtext = "RESERVED_CT_1";
4309 logtext = "RESERVED_CT_2";
4312 logtext = "REVERSE_CHARGING";
4315 logtext = "REMOTE_HOLD";
4318 logtext = "REMOTE_RETRIEVAL";
4321 logtext = "CALL_IS_DIVERTING";
4324 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
4328 trace_header("NOTIFY", dir);
4329 if (dir == DIRECTION_OUT)
4330 add_trace("to", NULL, "CH(%lu)", port_id);
4331 if (dir == DIRECTION_IN)
4332 add_trace("from", NULL, "CH(%lu)", port_id);
4333 if (param->notifyinfo.notify)
4334 add_trace("indicator", NULL, "%s", logtext);
4335 if (param->notifyinfo.id[0])
4337 add_trace("redir'on", "number", "%s", numberrize_callerinfo(param->notifyinfo.id, param->notifyinfo.ntype, options.national, options.international));
4338 switch(param->notifyinfo.present)
4340 case INFO_PRESENT_RESTRICTED:
4341 add_trace("redir'on", "present", "restricted");
4343 case INFO_PRESENT_ALLOWED:
4344 add_trace("redir'on", "present", "allowed");
4347 add_trace("redir'on", "present", "not available");
4350 if (param->notifyinfo.display[0])
4351 add_trace("display", NULL, "%s", param->notifyinfo.display);
4355 case MESSAGE_INFORMATION:
4356 trace_header("INFORMATION", dir);
4357 if (dir == DIRECTION_OUT)
4358 add_trace("to", NULL, "CH(%lu)", port_id);
4359 if (dir == DIRECTION_IN)
4360 add_trace("from", NULL, "CH(%lu)", port_id);
4361 if (param->information.id[0])
4362 add_trace("dialing", NULL, "%s", param->information.id);
4363 if (param->information.display[0])
4364 add_trace("display", NULL, "%s", param->information.display);
4365 if (param->information.sending_complete)
4366 add_trace("complete", NULL, "true", param->information.sending_complete);
4370 case MESSAGE_FACILITY:
4371 trace_header("FACILITY", dir);
4372 if (dir == DIRECTION_OUT)
4373 add_trace("to", NULL, "CH(%lu)", port_id);
4374 if (dir == DIRECTION_IN)
4375 add_trace("from", NULL, "CH(%lu)", port_id);
4380 trace_header("TONE", dir);
4381 if (dir == DIRECTION_OUT)
4382 add_trace("to", NULL, "CH(%lu)", port_id);
4383 if (dir == DIRECTION_IN)
4384 add_trace("from", NULL, "CH(%lu)", port_id);
4385 if (param->tone.name[0])
4387 add_trace("directory", NULL, "%s", param->tone.dir[0]?param->tone.dir:"default");
4388 add_trace("name", NULL, "%s", param->tone.name);
4390 add_trace("off", NULL, NULL);
4394 case MESSAGE_SUSPEND:
4395 case MESSAGE_RESUME:
4396 if (message_type == MESSAGE_SUSPEND)
4397 trace_header("SUSPEND", dir);
4399 trace_header("RESUME", dir);
4400 if (dir == DIRECTION_OUT)
4401 add_trace("to", NULL, "CH(%lu)", port_id);
4402 if (dir == DIRECTION_IN)
4403 add_trace("from", NULL, "CH(%lu)", port_id);
4404 if (param->parkinfo.len)
4405 add_trace("length", NULL, "%d", param->parkinfo.len);
4410 case MESSAGE_BCHANNEL:
4411 trace_header("BCHANNEL", dir);
4412 switch(param->bchannel.type)
4414 case BCHANNEL_REQUEST:
4415 add_trace("type", NULL, "request");
4417 case BCHANNEL_ASSIGN:
4418 add_trace("type", NULL, "assign");
4420 case BCHANNEL_ASSIGN_ACK:
4421 add_trace("type", NULL, "assign_ack");
4423 case BCHANNEL_REMOVE:
4424 add_trace("type", NULL, "remove");
4426 case BCHANNEL_REMOVE_ACK:
4427 add_trace("type", NULL, "remove_ack");
4430 if (param->bchannel.addr)
4431 add_trace("address", NULL, "%x", param->bchannel.addr);
4437 PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message_type);
4441 void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cause, int location, const char *display)
4443 struct lcr_msg *message;
4447 if (!portlist->port_id)
4450 if (!e_connectedmode)
4452 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT);
4453 message->param.disconnectinfo.cause = cause;
4454 message->param.disconnectinfo.location = location;
4456 SCPY(message->param.disconnectinfo.display, display);
4458 SCPY(message->param.disconnectinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4461 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
4463 SCPY(message->param.notifyinfo.display, display);
4465 SCPY(message->param.notifyinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4467 message_put(message);
4468 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);