1 /*****************************************************************************\
3 ** Linux Call Router **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
8 ** The EndpointAppPBX implements PBX4Linux **
10 \*****************************************************************************/
15 #include <sys/types.h>
23 class EndpointAppPBX *apppbx_first = NULL;
26 * EndpointAppPBX constructor
28 EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint) : EndpointApp(epoint)
30 class EndpointAppPBX **apppointer;
32 /* add application to chain */
34 apppointer = &apppbx_first;
36 apppointer = &((*apppointer)->next);
40 memset(&e_ext, 0, sizeof(struct extension));
41 e_ext.rights = 4; /* international */
42 e_ext.rxvol = e_ext.txvol = 256;
43 e_state = EPOINT_STATE_IDLE;
44 e_ext.number[0] = '\0';
45 e_extension_interface[0] = '\0';
46 memset(&e_callerinfo, 0, sizeof(struct caller_info));
47 memset(&e_dialinginfo, 0, sizeof(struct dialing_info));
48 memset(&e_connectinfo, 0, sizeof(struct connect_info));
49 memset(&e_redirinfo, 0, sizeof(struct redir_info));
50 memset(&e_capainfo, 0, sizeof(struct capa_info));
53 e_ruleset = ruleset_main;
55 e_rule = e_ruleset->rule_first;
60 e_match_to_action = NULL;
62 e_extdialing = e_dialinginfo.id;
66 // e_join_tone[0] = e_hold_tone[0] = '\0';
67 e_join_pattern /*= e_hold_pattern*/ = 0;
70 e_adminid = 0; // will be set, if call was initiated via admin socket
75 e_cbdialing[0] = '\0';
78 memset(&e_callbackinfo, 0, sizeof(struct caller_info));
85 e_password_timeout = 0;
86 e_multipoint_cause = 0;
87 e_multipoint_location = 0;
88 e_dialing_queue[0] = '\0';
90 e_crypt_state = CM_ST_NULL;
91 e_crypt_keyengine_busy = 0;
92 e_crypt_info[0] = '\0';
95 e_tx_state = NOTIFY_STATE_ACTIVE;
96 e_rx_state = NOTIFY_STATE_ACTIVE;
97 e_join_cause = e_join_location = 0;
98 /*********************************
99 *********************************
100 ********* ATTENTION *************
101 *********************************
102 *********************************/
103 /* if you add new values, that must be initialized, also check if they must
104 * be initialized when doing callback
110 * EpointAppPBX destructor
112 EndpointAppPBX::~EndpointAppPBX(void)
114 class EndpointAppPBX *temp, **tempp;
118 tempp = &apppbx_first;
128 FATAL("Endpoint not in endpoint's list.\n");
135 * trace header for application
137 void EndpointAppPBX::trace_header(char *name, int direction)
141 char msgtext[sizeof(_trace.name)];
145 /* init trace with given values */
148 numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype),
152 ea_endpoint->ep_serial,
159 /* set new endpoint state
161 void EndpointAppPBX::new_state(int state)
164 if (e_state != state)
166 trace_header("NEW STATE", DIRECTION_NONE);
167 add_trace("state", "old", "%s", state_name[e_state]);
168 add_trace("state", "new", "%s", state_name[state]);
177 * out==0: incomming caller id, out==1: outgoing caller id
179 void EndpointAppPBX::screen(int out, char *id, int idsize, int *type, int *present, struct interface *interface)
182 struct interface_msn *ifmsn;
183 struct interface_screen *ifscreen;
186 /* screen incoming caller id */
189 /* check for MSN numbers, use first MSN if no match */
191 ifmsn = interface->ifmsn;
196 if (!strcmp(ifmsn->msn, id))
204 trace_header("SCREEN (found in MSN list)", DIRECTION_IN);
205 add_trace("msn", NULL, "%s", id);
208 if (!ifmsn && msn1) // not in list, first msn given
210 trace_header("SCREEN (not found MSN in list)", DIRECTION_IN);
211 add_trace("msn", "given", "%s", id);
212 add_trace("msn", "used", "%s", msn1);
214 UNCPY(id, msn1, idsize);
219 /* check screen list */
221 ifscreen = interface->ifscreen_out;
223 ifscreen = interface->ifscreen_in;
226 if (ifscreen->match_type==-1 || ifscreen->match_type==*type)
227 if (ifscreen->match_present==-1 || ifscreen->match_present==*present)
229 if (strchr(ifscreen->match,'%'))
231 if (!strncmp(ifscreen->match, id, strchr(ifscreen->match,'%')-ifscreen->match))
235 if (!strcmp(ifscreen->match, id))
239 ifscreen = ifscreen->next;
241 if (ifscreen) // match
243 trace_header("SCREEN (found in screen list)", out?DIRECTION_OUT:DIRECTION_IN);
246 case INFO_NTYPE_UNKNOWN:
247 add_trace("given", "type", "unknown");
249 case INFO_NTYPE_SUBSCRIBER:
250 add_trace("given", "type", "subscriber");
252 case INFO_NTYPE_NATIONAL:
253 add_trace("given", "type", "national");
255 case INFO_NTYPE_INTERNATIONAL:
256 add_trace("given", "type", "international");
261 case INFO_PRESENT_ALLOWED:
262 add_trace("given", "present", "allowed");
264 case INFO_PRESENT_RESTRICTED:
265 add_trace("given", "present", "restricted");
267 case INFO_PRESENT_NOTAVAIL:
268 add_trace("given", "present", "not available");
271 add_trace("given", "id", "%s", id[0]?id:"<empty>");
272 if (ifscreen->result_type != -1)
274 *type = ifscreen->result_type;
277 case INFO_NTYPE_UNKNOWN:
278 add_trace("used", "type", "unknown");
280 case INFO_NTYPE_SUBSCRIBER:
281 add_trace("used", "type", "subscriber");
283 case INFO_NTYPE_NATIONAL:
284 add_trace("used", "type", "national");
286 case INFO_NTYPE_INTERNATIONAL:
287 add_trace("used", "type", "international");
291 if (ifscreen->result_present != -1)
293 *present = ifscreen->result_present;
296 case INFO_PRESENT_ALLOWED:
297 add_trace("used", "present", "allowed");
299 case INFO_PRESENT_RESTRICTED:
300 add_trace("used", "present", "restricted");
302 case INFO_PRESENT_NOTAVAIL:
303 add_trace("used", "present", "not available");
307 if (strchr(ifscreen->match,'%'))
309 SCPY(suffix, strchr(ifscreen->match,'%') - ifscreen->match + id);
310 UNCPY(id, ifscreen->result, idsize);
312 if (strchr(ifscreen->result,'%'))
314 *strchr(ifscreen->result,'%') = '\0';
315 UNCAT(id, suffix, idsize);
320 UNCPY(id, ifscreen->result, idsize);
323 add_trace("used", "id", "%s", id[0]?id:"<empty>");
328 /* release join and port (as specified)
330 void EndpointAppPBX::release(int release, int joinlocation, int joincause, int portlocation, int portcause)
332 struct port_list *portlist;
333 struct message *message;
336 /* message to test call */
337 admin_call_response(e_adminid, ADMIN_CALL_RELEASE, "", joincause, joinlocation, 0);
339 /* if a release is pending */
340 if (release==RELEASE_JOIN || release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY)
342 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): do pending release (joincause %d location %d)\n", ea_endpoint->ep_serial, joincause, joinlocation);
343 if (ea_endpoint->ep_join_id)
345 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_RELEASE);
346 message->param.disconnectinfo.cause = joincause;
347 message->param.disconnectinfo.location = joinlocation;
348 message_put(message);
349 ea_endpoint->ep_join_id = 0;
353 if (release != RELEASE_PORT_JOINONLY)
356 join_release(e_hold_id, ea_endpoint->ep_serial, 1, joinlocation, joincause);
361 if (release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY)
363 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release (portcause %d portlocation)\n", ea_endpoint->ep_serial, portcause, portlocation);
364 while((portlist = ea_endpoint->ep_portlist))
366 if (portlist->port_id)
368 SPRINT(cause, "cause_%02x", portcause);
369 set_tone(portlist, cause);
370 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
371 message->param.disconnectinfo.cause = portcause;
372 message->param.disconnectinfo.location = portlocation;
373 message_put(message);
374 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
376 ea_endpoint->free_portlist(portlist);
379 /* if callback is enabled, call back with the given caller id */
382 /* reset some stuff */
383 new_state(EPOINT_STATE_IDLE);
384 memset(&e_connectinfo, 0, sizeof(struct connect_info));
385 memset(&e_redirinfo, 0, sizeof(struct redir_info));
386 e_start = e_stop = 0;
387 e_ruleset = ruleset_main;
389 e_rule = e_ruleset->rule_first;
391 e_action_timeout = 0;
393 e_match_to_action = NULL;
395 e_extdialing = e_dialinginfo.id;
402 e_multipoint_cause = 0;
403 e_multipoint_location = 0;
404 e_dialing_queue[0] = '\0';
406 e_crypt_state = CM_ST_NULL;
407 e_crypt_keyengine_busy = 0;
408 e_crypt_info[0] = '\0';
412 e_tx_state = NOTIFY_STATE_ACTIVE;
413 e_rx_state = NOTIFY_STATE_ACTIVE;
414 e_join_cause = e_join_location = 0;
416 /* the caller info of the callback user */
417 memcpy(&e_callbackinfo, &e_callerinfo, sizeof(e_callbackinfo));
418 memset(&e_dialinginfo, 0, sizeof(e_dialinginfo));
419 /* create dialing by callerinfo */
420 if (e_ext.number[0] && e_extension_interface[0])
422 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to internal: %s interface %s\n", ea_endpoint->ep_serial, e_ext.number, e_extension_interface);
423 /* create callback to the current terminal */
424 SCPY(e_dialinginfo.id, e_ext.number);
425 SCPY(e_dialinginfo.interfaces, e_extension_interface);
426 e_dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
427 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
432 SCPY(e_dialinginfo.id, e_cbto);
435 /* numberrize caller id and use it to dial to the callback */
436 SCPY(e_dialinginfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype));
438 e_dialinginfo.itype = INFO_ITYPE_ISDN;
439 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
440 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to external: %s\n", ea_endpoint->ep_serial, e_dialinginfo.id);
445 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release of epoint itself.\n", ea_endpoint->ep_serial);
446 ea_endpoint->ep_use--; /* when e_lock is 0, the endpoint will be deleted */
452 /* cancel callerid if restricted, unless anon-ignore is enabled at extension or port is of type external (so called police gets caller id :)*/
453 void apply_callerid_restriction(int anon_ignore, char *id, int *ntype, int *present, int *screen, char *extension, char *name)
455 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");
457 /* caller id is not restricted, so we do nothing */
458 if (*present != INFO_PRESENT_RESTRICTED)
461 /* only extensions are restricted */
467 /* if we enabled anonymouse ignore */
471 /* else we remove the caller id */
475 *ntype = INFO_NTYPE_UNKNOWN;
477 // *screen = INFO_SCREEN_USER;
478 // maybe we should not make voip address anonymous
481 // maybe it's no fraud to present extension id
483 // extension[0] = '\0';
488 /* used display message to display callerid as available */
489 char *EndpointAppPBX::apply_callerid_display(char *id, int itype, int ntype, int present, int screen, char *extension, char *name)
491 static char display[81];
494 char *cid = numberrize_callerinfo(id, ntype);
496 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");
505 /* NOTE: is caller is is not available for this extesion, it has been removed by apply_callerid_restriction already */
507 /* internal extension's caller id */
508 if (extension[0] && e_ext.display_int)
511 SCAT(display, extension);
514 if (itype == INFO_ITYPE_VBOX)
515 SCAT(display, "(vbox)");
517 SCAT(display, "(int)");
520 /* external caller id */
521 if (!extension[0] && e_ext.display_ext)
527 if (present == INFO_PRESENT_RESTRICTED)
528 SCAT(display, "anonymous");
530 SCAT(display, "unknown");
537 /* display if callerid is anonymouse but available due anon-ignore */
538 if (e_ext.display_anon && present==INFO_PRESENT_RESTRICTED)
541 SCAT(display, "unknown");
544 SCAT(display, " anon");
547 /* display if callerid is anonymouse but available due anon-ignore */
548 if (e_ext.display_fake && screen==INFO_SCREEN_USER && present!=INFO_PRESENT_NULL)
554 if (present == INFO_PRESENT_RESTRICTED)
555 SCAT(display, "anonymous");
557 SCAT(display, "unknown");
562 SCAT(display, " fake");
566 if (name[0] && e_ext.display_name)
568 if (!display[0] && cid[0])
579 * uses the current state to notify activity
581 void EndpointAppPBX::notify_active(void)
583 struct port_list *portlist = ea_endpoint->ep_portlist;
584 struct message *message;
589 case NOTIFY_STATE_ACTIVE:
590 /* we are already active, so we don't do anything */
593 case NOTIFY_STATE_SUSPEND:
594 notify = INFO_NOTIFY_USER_RESUMED;
597 set_tone(portlist, NULL);
598 portlist = portlist->next;
600 portlist = ea_endpoint->ep_portlist;
603 case NOTIFY_STATE_HOLD:
604 notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
607 set_tone(portlist, NULL);
608 portlist = portlist->next;
610 portlist = ea_endpoint->ep_portlist;
613 case NOTIFY_STATE_CONFERENCE:
614 notify = INFO_NOTIFY_CONFERENCE_DISCONNECTED;
617 set_tone(portlist, NULL);
618 portlist = portlist->next;
620 portlist = ea_endpoint->ep_portlist;
624 PERROR("unknown e_tx_state = %d\n", e_tx_state);
630 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
631 message->param.notifyinfo.notify = notify;
632 message_put(message);
633 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
634 portlist = portlist->next;
640 * keypad functions during call. one example to use this is to put a call on hold or start a conference
642 void EndpointAppPBX::keypad_function(char digit)
645 /* we must be in a call, in order to send messages to the call */
646 if (e_ext.number[0] == '\0')
648 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) IGNORING keypad received not from extension.\n", ea_endpoint->ep_serial);
654 /* join conference */
656 if (ea_endpoint->ep_join_id == 0)
658 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad received during connect but not during a call.\n", ea_endpoint->ep_serial);
661 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join call with call on hold\n", ea_endpoint->ep_serial);
667 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) shared key encryption selected.\n", ea_endpoint->ep_serial);
671 /* crypt key-exchange */
673 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) key exchange encryption selected.\n", ea_endpoint->ep_serial);
679 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) encryption off selected.\n", ea_endpoint->ep_serial);
684 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) unsupported keypad digit '%c'.\n", ea_endpoint->ep_serial, digit);
689 /* set tone pattern for port */
690 void EndpointAppPBX::set_tone(struct port_list *portlist, char *tone)
692 struct message *message;
697 /* store for suspended processes */
702 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no endpoint to notify tone.\n", ea_endpoint->ep_serial);
706 if (e_join_pattern /* pattern are provided */
707 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_SETUP)
708 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_OVERLAP)
709 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_IN_PROCEEDING)
710 && !(e_ext.own_alerting && e_state == EPOINT_STATE_IN_ALERTING)
711 && !(e_ext.own_cause && e_state == EPOINT_STATE_IN_DISCONNECT)
712 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_SETUP)
713 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_OVERLAP)
714 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_OUT_PROCEEDING)
715 && !(e_ext.own_alerting && e_state == EPOINT_STATE_OUT_ALERTING)
716 && !(e_ext.own_cause && e_state == EPOINT_STATE_OUT_DISCONNECT)
717 && tone[0] && !!strncmp(tone,"crypt_*",6))
719 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) tone not provided since patterns are available\n", ea_endpoint->ep_serial);
725 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_TONE);
726 SCPY(message->param.tone.dir, e_ext.tones_dir[0]?e_ext.tones_dir:options.tones_dir);
727 SCPY(message->param.tone.name, tone);
728 message_put(message);
729 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
735 * hunts an mISDNport that is available for an outgoing call
736 * if no ifname was given, any interface that is not an extension
739 struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel)
741 struct interface *interface;
742 struct interface_port *ifport, *ifport_start;
743 struct select_channel *selchannel;
744 struct mISDNport *mISDNport;
747 interface = interface_first;
749 /* first find the given interface or, if not given, one with no extension */
754 /* check for given interface */
757 if (!strcasecmp(interface->name, ifname))
759 /* found explicit interface */
760 trace_header("CHANNEL SELECTION (found interface)", DIRECTION_NONE);
761 add_trace("interface", NULL, "%s", ifname);
768 if (!interface->extension)
770 /* found non extension */
771 trace_header("CHANNEL SELECTION (found non extension interface)", DIRECTION_NONE);
772 add_trace("interface", NULL, "%s", interface->name);
778 interface = interface->next;
782 /* see if interface has ports */
783 if (!interface->ifport)
786 trace_header("CHANNEL SELECTION (interface has no active ports, skipping)", DIRECTION_NONE);
787 add_trace("interface", NULL, "%s", interface->name);
789 interface = interface->next;
793 /* select port by algorithm */
794 ifport_start = interface->ifport;
796 if (interface->hunt == HUNT_ROUNDROBIN)
798 while(ifport_start->next && index<interface->hunt_next)
800 ifport_start = ifport_start->next;
803 trace_header("CHANNEL SELECTION (starting round-robin)", DIRECTION_NONE);
804 add_trace("port", NULL, "%d", ifport_start->portnum);
805 add_trace("position", NULL, "%d", index);
810 ifport = ifport_start;
813 /* see if port is available */
814 if (!ifport->mISDNport)
816 trace_header("CHANNEL SELECTION (port not available, skipping)", DIRECTION_NONE);
817 add_trace("port", NULL, "%d", ifport->portnum);
818 add_trace("position", NULL, "%d", index);
822 mISDNport = ifport->mISDNport;
824 /* see if port is administratively blocked */
827 trace_header("CHANNEL SELECTION (port blocked by admin, skipping)", DIRECTION_NONE);
828 add_trace("port", NULL, "%d", ifport->portnum);
829 add_trace("position", NULL, "%d", index);
834 /* see if link is up on PTP*/
835 if (mISDNport->ptp && !mISDNport->l2link)
837 trace_header("CHANNEL SELECTION (port is ptp with layer 2 down, skipping)", DIRECTION_NONE);
838 add_trace("port", NULL, "%d", ifport->portnum);
839 add_trace("position", NULL, "%d", index);
844 /* check for channel form selection list */
846 selchannel = ifport->out_channel;
849 switch(selchannel->channel)
851 case CHANNEL_FREE: /* free channel */
852 if (mISDNport->b_reserved >= mISDNport->b_num)
853 break; /* all channel in use or reserverd */
856 while(i < mISDNport->b_num)
858 if (mISDNport->b_port[i] == NULL)
860 *channel = i+1+(i>=15);
861 trace_header("CHANNEL SELECTION (selecting free channel)", DIRECTION_NONE);
862 add_trace("port", NULL, "%d", ifport->portnum);
863 add_trace("position", NULL, "%d", index);
864 add_trace("channel", NULL, "%d", *channel);
872 case CHANNEL_ANY: /* don't ask for channel */
873 if (mISDNport->b_reserved >= mISDNport->b_num)
875 break; /* all channel in use or reserverd */
877 trace_header("CHANNEL SELECTION (using 'any channel')", DIRECTION_NONE);
878 add_trace("port", NULL, "%d", ifport->portnum);
879 add_trace("position", NULL, "%d", index);
881 *channel = CHANNEL_ANY;
884 case CHANNEL_NO: /* call waiting */
885 trace_header("CHANNEL SELECTION (using 'no channel', call-waiting)", DIRECTION_NONE);
886 add_trace("port", NULL, "%d", ifport->portnum);
887 add_trace("position", NULL, "%d", index);
889 *channel = CHANNEL_NO;
893 if (selchannel->channel<1 || selchannel->channel==16)
894 break; /* invalid channels */
895 i = selchannel->channel-1-(selchannel->channel>=17);
896 if (i >= mISDNport->b_num)
897 break; /* channel not in port */
898 if (mISDNport->b_port[i] == NULL)
900 *channel = selchannel->channel;
901 trace_header("CHANNEL SELECTION (selecting given channel)", DIRECTION_NONE);
902 add_trace("port", NULL, "%d", ifport->portnum);
903 add_trace("position", NULL, "%d", index);
904 add_trace("channel", NULL, "%d", *channel);
911 break; /* found channel */
912 selchannel = selchannel->next;
915 /* if channel was found, return mISDNport and channel */
918 /* setting next port to start next time */
919 if (interface->hunt == HUNT_ROUNDROBIN)
924 interface->hunt_next = index;
930 trace_header("CHANNEL SELECTION (skipping, no channel found)", DIRECTION_NONE);
931 add_trace("port", NULL, "%d", ifport->portnum);
932 add_trace("position", NULL, "%d", index);
936 /* go next port, until all ports are checked */
938 ifport = ifport->next;
942 ifport = interface->ifport;
944 if (ifport != ifport_start)
947 return(NULL); /* no port found */
950 /* outgoing setup to port(s)
951 * ports will be created and a setup is sent if everything is ok. otherwhise
952 * the endpoint is destroyed.
954 void EndpointAppPBX::out_setup(void)
956 struct dialing_info dialinginfo;
958 // class pdss1 *pdss1;
959 struct port_list *portlist;
960 struct message *message;
962 int cause = CAUSE_RESSOURCEUNAVAIL;
965 struct mISDNport *mISDNport;
968 class EndpointAppPBX *atemp;
969 // char allowed_ports[256];
971 char ifname[sizeof(e_ext.interfaces)],
973 struct port_settings port_settings;
977 /* create settings for creating port */
978 memset(&port_settings, 0, sizeof(port_settings));
980 SCPY(port_settings.tones_dir, e_ext.tones_dir);
982 SCPY(port_settings.tones_dir, options.tones_dir);
983 port_settings.tout_setup = e_ext.tout_setup;
984 port_settings.tout_dialing = e_ext.tout_dialing;
985 port_settings.tout_proceeding = e_ext.tout_proceeding;
986 port_settings.tout_alerting = e_ext.tout_alerting;
987 port_settings.tout_disconnect = e_ext.tout_disconnect;
988 // port_settings.tout_hold = e_ext.tout_hold;
989 // port_settings.tout_park = e_ext.tout_park;
990 port_settings.no_seconds = e_ext.no_seconds;
992 /* 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 */
994 /* check what dialinginfo.itype we got */
995 switch(e_dialinginfo.itype)
997 /* *********************** call to extension or vbox */
998 case INFO_ITYPE_ISDN_EXTENSION:
999 /* check if we deny incoming calls when we use an extension */
1000 if (e_ext.noknocking)
1002 atemp = apppbx_first;
1006 if (!strcmp(atemp->e_ext.number, e_ext.number))
1008 atemp = atemp->next;
1012 PERROR("EPOINT(%d) noknocking and currently a call\n", ea_endpoint->ep_serial);
1013 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYSPE_ join, port */
1014 return; /* must exit here */
1017 /* FALL THROUGH !!!! */
1018 case INFO_ITYPE_VBOX:
1019 /* get dialed extension's info */
1020 // SCPY(exten, e_dialinginfo.id);
1021 // if (strchr(exten, ','))
1022 // *strchr(exten, ',') = '\0';
1023 // if (!read_extension(&e_ext, exten))
1024 if (!read_extension(&e_ext, e_dialinginfo.id))
1026 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) extension %s not configured\n", ea_endpoint->ep_serial, e_dialinginfo.id);
1027 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1028 return; /* must exit here */
1031 if (e_dialinginfo.itype == INFO_ITYPE_VBOX)
1033 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing directly to VBOX\n", ea_endpoint->ep_serial);
1038 /* string from unconditional call forward (cfu) */
1042 /* present to forwarded party */
1043 if (e_ext.anon_ignore && e_callerinfo.id[0])
1045 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1047 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
1051 /* string from busy call forward (cfb) */
1055 class EndpointAppPBX *checkapp = apppbx_first;
1058 if (checkapp != this) /* any other endpoint except our own */
1060 if (!strcmp(checkapp->e_ext.number, e_ext.number))
1062 /* present to forwarded party */
1063 if (e_ext.anon_ignore && e_callerinfo.id[0])
1065 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1067 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
1071 checkapp = checkapp->next;
1075 /* string from no-response call forward (cfnr) */
1079 /* when cfnr is done, out_setup() will setup the call */
1082 /* present to forwarded party */
1083 if (e_ext.anon_ignore && e_callerinfo.id[0])
1085 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1089 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
1091 e_cfnr_release = now + e_ext.cfnr_delay;
1092 e_cfnr_call = now + e_ext.cfnr_delay + 1; /* call one second after release */
1093 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);
1097 /* call to all internal interfaces */
1098 p = e_ext.interfaces;
1099 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) generating multiple joins for extension %s to interfaces %s\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
1103 while(*p!=',' && *p!='\0')
1105 SCCAT(ifname, *p++);
1108 /* found interface */
1109 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
1110 /* hunt for mISDNport and create Port */
1111 mISDNport = hunt_port(ifname, &channel);
1114 trace_header("INTERFACE (not found or busy)", DIRECTION_NONE);
1115 add_trace("interface", NULL, "%s", ifname);
1119 /* creating INTERNAL port */
1120 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1121 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force);
1123 FATAL("No memory for DSS1 Port instance\n");
1124 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
1125 memset(&dialinginfo, 0, sizeof(dialinginfo));
1126 SCPY(dialinginfo.id, e_dialinginfo.id);
1127 dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
1128 dialinginfo.ntype = e_dialinginfo.ntype;
1129 /* create port_list relation */
1130 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
1133 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1135 goto check_anycall_intern;
1137 /* directory.list */
1138 if (e_callerinfo.id[0] && (e_ext.centrex || e_ext.display_name))
1140 dirname = parse_directory(e_callerinfo.id, e_callerinfo.ntype);
1142 SCPY(e_callerinfo.name, dirname);
1144 // dss1 = (class Pdss1 *)port;
1146 //printf("INTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1147 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1148 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1149 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1150 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1151 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1152 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1153 //terminal if (e_dialinginfo.id)
1154 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1155 /* handle restricted caller ids */
1156 apply_callerid_restriction(e_ext.anon_ignore, 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);
1157 apply_callerid_restriction(e_ext.anon_ignore, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, 0, message->param.setup.redirinfo.extension, NULL);
1158 /* display callerid if desired for extension */
1159 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));
1160 //printf("\n\ndisplay = %s\n\n\n",message->param.setup.callerinfo.display);
1161 /* use cnip, if enabld */
1163 message->param.setup.callerinfo.name[0] = '\0';
1164 /* screen clip if prefix is required */
1165 if (message->param.setup.callerinfo.id[0] && e_ext.clip_prefix[0])
1167 SCPY(message->param.setup.callerinfo.id, e_ext.clip_prefix);
1168 SCAT(message->param.setup.callerinfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype));
1169 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1171 /* use internal caller id */
1172 if (e_callerinfo.extension[0] && (message->param.setup.callerinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
1174 SCPY(message->param.setup.callerinfo.id, e_callerinfo.extension);
1175 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1177 message_put(message);
1178 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1182 /* string from parallel call forward (cfp) */
1186 if (e_ext.anon_ignore && e_callerinfo.id[0])
1188 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1192 vbox_only: /* entry point for answering machine only */
1193 cfu_only: /* entry point for cfu */
1194 cfb_only: /* entry point for cfb */
1195 cfnr_only: /* entry point for cfnr */
1196 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call extension %s for external destiantion(s) '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
1201 /* only if vbox should be dialed, and terminal is given */
1202 if (!strcmp(p, "vbox") && e_ext.number[0])
1204 /* go to the end of p */
1207 /* answering vbox call */
1208 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) answering machine\n", ea_endpoint->ep_serial);
1210 if (!(port = new VBoxPort(PORT_TYPE_VBOX_OUT, &port_settings)))
1211 FATAL("No memory for VBOX Port instance\n");
1212 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocated port %s\n", ea_endpoint->ep_serial, port->p_name);
1213 UCPY(cfp, e_ext.number); /* cfp or any other direct forward/vbox */
1217 while(*p!=',' && *p!='\0')
1222 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cfp external %s\n", ea_endpoint->ep_serial, cfp);
1223 /* hunt for mISDNport and create Port */
1224 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1227 /* creating EXTERNAL port*/
1228 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1229 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)))
1230 FATAL("No memory for DSS1 Port instance\n");
1231 earlyb = mISDNport->earlyb;
1235 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1236 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1242 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port found or created, which is idle.\n", ea_endpoint->ep_serial);
1243 goto check_anycall_intern;
1245 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found or created port %s\n", ea_endpoint->ep_serial, port->p_name);
1246 memset(&dialinginfo, 0, sizeof(dialinginfo));
1247 SCPY(dialinginfo.id, cfp);
1248 dialinginfo.itype = INFO_ITYPE_ISDN;
1249 dialinginfo.ntype = e_dialinginfo.ntype;
1250 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
1253 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1255 goto check_anycall_intern;
1257 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1258 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1259 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1260 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1261 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1262 /* if clip is hidden */
1263 if (e_ext.clip==CLIP_HIDE && port->p_type!=PORT_TYPE_VBOX_OUT)
1265 SCPY(message->param.setup.callerinfo.id, e_ext.callerid);
1266 SCPY(message->param.setup.callerinfo.extension, e_ext.number);
1267 message->param.setup.callerinfo.ntype = e_ext.callerid_type;
1268 message->param.setup.callerinfo.present = e_ext.callerid_present;
1270 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1271 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1272 //terminal if (e_dialinginfo.id)
1273 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1274 /* handle restricted caller ids */
1275 apply_callerid_restriction(e_ext.anon_ignore, 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);
1276 apply_callerid_restriction(e_ext.anon_ignore, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, 0, message->param.setup.redirinfo.extension, NULL);
1277 /* display callerid if desired for extension */
1278 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));
1279 message_put(message);
1280 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1284 check_anycall_intern:
1285 /* now we have all ports created */
1288 trace_header("INTERFACE (no extension's interface)", DIRECTION_NONE);
1290 if (!ea_endpoint->ep_join_id)
1292 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1293 return; /* must exit here */
1297 /* *********************** external call */
1299 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id);
1300 /* call to extenal interfaces */
1301 p = e_dialinginfo.id;
1305 while(*p!=',' && *p!='\0')
1306 SCCAT(number, *p++);
1310 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");
1311 /* hunt for mISDNport and create Port */
1312 /* hunt for mISDNport and create Port */
1313 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1316 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1317 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1319 goto check_anycall_extern;
1321 /* creating EXTERNAL port*/
1322 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1323 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)))
1324 FATAL("No memory for DSS1 Port instance\n");
1325 earlyb = mISDNport->earlyb;
1326 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
1327 memset(&dialinginfo, 0, sizeof(dialinginfo));
1328 SCPY(dialinginfo.id, number);
1329 dialinginfo.itype = INFO_ITYPE_ISDN;
1330 dialinginfo.ntype = e_dialinginfo.ntype;
1331 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
1334 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1336 goto check_anycall_extern;
1338 // dss1 = (class Pdss1 *)port;
1339 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1340 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1341 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1342 SCPY(message->param.setup.dialinginfo.id, number);
1343 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1344 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1345 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1346 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1347 //terminal if (e_dialinginfo.id)
1348 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1349 /* handle restricted caller ids */
1350 apply_callerid_restriction(e_ext.anon_ignore, 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);
1351 apply_callerid_restriction(e_ext.anon_ignore, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, 0, message->param.setup.redirinfo.extension, NULL);
1352 /* display callerid if desired for extension */
1353 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));
1354 message_put(message);
1355 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1359 check_anycall_extern:
1360 /* now we have all ports created */
1363 trace_header("INTERFACE (no free ports found)", DIRECTION_NONE);
1365 if (!ea_endpoint->ep_join_id)
1367 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1368 return; /* must exit here */
1376 /* handler for endpoint
1380 int EndpointAppPBX::handler(void)
1382 if (e_crypt_state!=CM_ST_NULL)
1387 /* process answering machine (play) handling */
1390 if (e_action->index == ACTION_VBOX_PLAY)
1393 /* process action timeout */
1394 if (e_action_timeout)
1395 if (now_d >= e_action_timeout)
1397 if (e_state!=EPOINT_STATE_CONNECT)
1400 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current action timed out.\n", ea_endpoint->ep_serial);
1401 e_multipoint_cause = 0;
1402 e_multipoint_location = 0;
1403 new_state(EPOINT_STATE_IN_OVERLAP);
1406 return(1); /* we must exit, because our endpoint might be gone */
1408 e_action_timeout = 0;
1411 /* process action timeout */
1412 if (e_match_timeout)
1413 if (now_d >= e_match_timeout)
1416 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we got a match timeout.\n", ea_endpoint->ep_serial);
1418 return(1); /* we must exit, because our endpoint might be gone */
1423 /* process redialing (epoint redials to port) */
1426 if (now_d >= e_redial)
1429 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial.\n", ea_endpoint->ep_serial);
1431 new_state(EPOINT_STATE_OUT_SETUP);
1432 /* call special setup routine */
1439 /* process powerdialing (epoint redials to epoint) */
1440 if (e_powerdialing > 0)
1442 if (now_d >= e_powerdialing)
1444 e_powerdialing = -1; /* leave power dialing on */
1445 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial of powerdial.\n", ea_endpoint->ep_serial);
1448 e_ruleset = ruleset_main;
1450 e_rule = e_ruleset->rule_first;
1452 new_state(EPOINT_STATE_IN_OVERLAP);
1458 /* process call forward no response */
1461 struct port_list *portlist;
1462 struct message *message;
1464 if (now >= e_cfnr_release)
1466 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-no-response time has expired, hanging up.\n", ea_endpoint->ep_serial);
1469 /* release all ports */
1470 while((portlist = ea_endpoint->ep_portlist))
1472 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1473 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
1474 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1475 message_put(message);
1476 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1477 ea_endpoint->free_portlist(portlist);
1480 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1481 message->param.audiopath = CHANNEL_STATE_HOLD;
1482 message_put(message);
1483 /* indicate no patterns */
1484 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1485 message_put(message);
1486 /* set setup state, since we have no response from the new join */
1487 new_state(EPOINT_STATE_OUT_SETUP);
1492 if (now >= e_cfnr_call)
1494 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-busy time has expired, calling the forwarded number: %s.\n", ea_endpoint->ep_serial, e_ext.cfnr);
1500 /* handle connection to user */
1501 if (e_state == EPOINT_STATE_IDLE)
1503 /* epoint is idle, check callback */
1505 if (now_d >= e_callback)
1507 e_callback = 0; /* done with callback */
1508 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting callback.\n", ea_endpoint->ep_serial);
1509 new_state(EPOINT_STATE_OUT_SETUP);
1515 /* check for password timeout */
1517 if (e_action->index==ACTION_PASSWORD || e_action->index==ACTION_PASSWORD_WRITE)
1519 struct port_list *portlist;
1521 if (now >= e_password_timeout)
1523 e_ruleset = ruleset_main;
1525 e_rule = e_ruleset->rule_first;
1527 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) password timeout %s\n", ea_endpoint->ep_serial, e_extdialing);
1528 trace_header("PASSWORD timeout", DIRECTION_NONE);
1530 e_connectedmode = 0;
1532 new_state(EPOINT_STATE_OUT_DISCONNECT);
1533 portlist = ea_endpoint->ep_portlist;
1536 message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
1537 set_tone(portlist, "cause_10");
1547 /* doing a hookflash */
1548 void EndpointAppPBX::hookflash(void)
1552 /* be sure that we are active */
1554 e_tx_state = NOTIFY_STATE_ACTIVE;
1556 trace_header("HOOKFLASH DTMF", DIRECTION_NONE);
1558 if (ea_endpoint->ep_use > 1)
1560 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot hooflash while child process is running.\n", ea_endpoint->ep_serial);
1563 /* dialtone after pressing the hash key */
1564 process_hangup(e_join_cause, e_join_location);
1565 e_multipoint_cause = 0;
1566 e_multipoint_location = 0;
1567 port = find_port_id(ea_endpoint->ep_portlist->port_id);
1570 port->set_echotest(0);
1572 if (ea_endpoint->ep_join_id)
1574 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1576 e_ruleset = ruleset_main;
1578 e_rule = e_ruleset->rule_first;
1580 new_state(EPOINT_STATE_IN_OVERLAP);
1581 e_connectedmode = 1;
1582 SCPY(e_dialinginfo.id, e_ext.prefix);
1583 e_extdialing = e_dialinginfo.id;
1585 if (e_dialinginfo.id[0])
1587 set_tone(ea_endpoint->ep_portlist, "dialing");
1591 set_tone(ea_endpoint->ep_portlist, "dialpbx");
1598 /* messages from port
1600 /* port MESSAGE_SETUP */
1601 void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, union parameter *param)
1603 struct message *message;
1605 int writeext; /* flags need to write extension after modification */
1607 struct interface *interface;
1609 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1611 portlist->port_type = param->setup.port_type;
1612 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
1613 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
1614 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
1615 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
1616 e_dtmf = param->setup.dtmf;
1617 /* screen incoming caller id */
1618 interface = interface_first;
1621 if (!strcmp(e_callerinfo.interface, interface->name))
1625 interface = interface->next;
1628 screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface);
1630 /* process extension */
1631 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1633 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is extension\n", ea_endpoint->ep_serial);
1634 /* port makes call from extension */
1635 SCPY(e_callerinfo.extension, e_callerinfo.id);
1636 SCPY(e_ext.number, e_callerinfo.extension);
1637 SCPY(e_extension_interface, e_callerinfo.interface);
1640 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is external or voip\n", ea_endpoint->ep_serial);
1643 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1645 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1647 /* get extension's info about caller */
1648 if (!read_extension(&e_ext, e_ext.number))
1650 /* extension doesn't exist */
1651 trace_header("EXTENSION (not created)", DIRECTION_IN);
1652 add_trace("extension", NULL, "%s", e_ext.number);
1654 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
1655 new_state(EPOINT_STATE_OUT_DISCONNECT);
1656 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
1657 e_ext.number[0] = '\0'; /* no terminal */
1662 /* put prefix (next) in front of e_dialinginfo.id */
1665 SPRINT(buffer, "%s%s", e_ext.next, e_dialinginfo.id);
1666 SCPY(e_dialinginfo.id, buffer);
1667 e_ext.next[0] = '\0';
1669 } else if (e_ext.prefix[0])
1671 SPRINT(buffer, "%s%s", e_ext.prefix, e_dialinginfo.id);
1672 SCPY(e_dialinginfo.id, buffer);
1675 /* screen caller id by extension's config */
1676 e_callerinfo.screen = INFO_SCREEN_NETWORK;
1678 SCPY(e_callerinfo.name, e_ext.name);
1679 /* use caller id (or if exist: id_next_call) for this call */
1680 if (e_ext.id_next_call_present >= 0)
1682 SCPY(e_callerinfo.id, e_ext.id_next_call);
1683 /* if we restrict the pesentation */
1684 if (e_ext.id_next_call_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1685 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1686 else e_callerinfo.present = e_ext.id_next_call_present;
1687 e_callerinfo.ntype = e_ext.id_next_call_type;
1688 e_ext.id_next_call_present = -1;
1692 SCPY(e_callerinfo.id, e_ext.callerid);
1693 /* if we restrict the pesentation */
1694 if (e_ext.callerid_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1695 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1696 else e_callerinfo.present = e_ext.callerid_present;
1697 e_callerinfo.ntype = e_ext.callerid_type;
1700 /* extension is written */
1702 write_extension(&e_ext, e_ext.number);
1704 /* set volume of rx and tx */
1705 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1706 if (e_ext.txvol!=256 || e_ext.rxvol!=256)
1708 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
1709 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
1710 message->param.mISDNsignal.rxvol = e_ext.txvol;
1711 message->param.mISDNsignal.txvol = e_ext.rxvol;
1712 message_put(message);
1715 /* start recording if enabled */
1716 if (e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO))
1718 /* check if we are a terminal */
1719 if (e_ext.number[0] == '\0')
1720 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
1723 port = find_port_id(portlist->port_id);
1725 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
1730 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from external port\n", ea_endpoint->ep_serial);
1731 /* no terminal identification */
1732 e_ext.number[0] = '\0';
1733 e_extension_interface[0] = '\0';
1734 memset(&e_ext, 0, sizeof(e_ext));
1735 e_ext.rights = 4; /* right to dial internat */
1739 e_ruleset = ruleset_main;
1741 e_rule = e_ruleset->rule_first;
1743 e_extdialing = e_dialinginfo.id;
1744 new_state(EPOINT_STATE_IN_SETUP);
1745 if (e_dialinginfo.id[0])
1747 set_tone(portlist, "dialing");
1750 if (e_ext.number[0])
1751 set_tone(portlist, "dialpbx");
1753 set_tone(portlist, "dialtone");
1756 if (e_state == EPOINT_STATE_IN_SETUP)
1758 /* request MORE info, if not already at higher state */
1759 new_state(EPOINT_STATE_IN_OVERLAP);
1760 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_OVERLAP);
1761 message_put(message);
1762 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1766 /* port MESSAGE_INFORMATION */
1767 void EndpointAppPBX::port_information(struct port_list *portlist, int message_type, union parameter *param)
1769 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1773 /* turn off dtmf detection, in case dtmf is sent with keypad information */
1776 trace_header("DTMF (disabling due to keypad)", DIRECTION_IN);
1781 /* if vbox_play is done, the information are just used as they come */
1783 if (e_action->index == ACTION_VBOX_PLAY)
1785 /* concat dialing string */
1786 SCAT(e_dialinginfo.id, param->information.id);
1791 /* keypad when disconnect but in connected mode */
1792 if (e_state==EPOINT_STATE_OUT_DISCONNECT && e_connectedmode)
1794 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received after disconnect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1795 /* processing keypad function */
1796 if (param->information.id[0] == '0')
1803 /* keypad when connected */
1804 if (e_state == EPOINT_STATE_CONNECT)
1808 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1809 /* processing keypad function */
1810 if (param->information.id[0] == '0')
1814 if (param->information.id[0])
1815 keypad_function(param->information.id[0]);
1818 trace_header("DTMF (not enabled by extension's settings)", DIRECTION_IN);
1823 if (e_state != EPOINT_STATE_IN_OVERLAP)
1825 trace_header("DTMF (ignored, not connected and not dialing)", DIRECTION_IN);
1829 if (!param->information.id[0])
1831 if (e_dialinginfo.id[0]=='\0' && !e_action)
1833 set_tone(portlist, "dialing");
1836 if (e_action->index==ACTION_OUTDIAL
1837 || e_action->index==ACTION_EXTERNAL)
1840 set_tone(portlist, "dialing");
1841 else if (!e_extdialing[0])
1842 set_tone(portlist, "dialing");
1844 /* concat dialing string */
1845 SCAT(e_dialinginfo.id, param->information.id);
1849 /* port MESSAGE_DTMF */
1850 void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
1852 /* only if dtmf detection is enabled */
1855 trace_header("DTMF (disabled)", DIRECTION_IN);
1859 trace_header("DTMF", DIRECTION_IN);
1860 add_trace("digit", NULL, "%c", param->dtmf);
1864 NOTE: vbox is now handled due to overlap state
1865 /* if vbox_play is done, the dtmf digits are just used as they come */
1867 if (e_action->index == ACTION_VBOX_PLAY)
1869 /* concat dialing string */
1870 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id))
1872 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1873 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1876 /* continue to process *X# sequences */
1880 /* check for *X# sequence */
1881 if (e_state == EPOINT_STATE_CONNECT)
1883 if (e_dtmf_time+3 < now)
1885 /* the last digit was too far in the past to be a sequence */
1886 if (param->dtmf == '*')
1887 /* only start is allowed in the sequence */
1893 /* we have a sequence of digits, see what we got */
1894 if (param->dtmf == '*')
1896 else if (param->dtmf>='0' && param->dtmf<='9')
1898 /* we need to have a star before we receive the digit of the sequence */
1899 if (e_dtmf_last == '*')
1900 e_dtmf_last = param->dtmf;
1901 } else if (param->dtmf == '#')
1904 if (e_dtmf_last>='0' && e_dtmf_last<='9')
1906 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf sequence *%c# detected.\n", ea_endpoint->ep_serial, e_dtmf_last);
1907 if (e_dtmf_last == '0')
1912 /* processing keypad function */
1914 keypad_function(e_dtmf_last);
1920 /* set last time of dtmf */
1925 /* check for ## hookflash during dialing */
1927 if (e_action->index==ACTION_PASSWORD
1928 || e_action->index==ACTION_PASSWORD_WRITE)
1930 if (param->dtmf=='#') /* current digit is '#' */
1932 if (e_state==EPOINT_STATE_IN_DISCONNECT
1933 || (e_state!=EPOINT_STATE_CONNECT && e_dtmf_time+3>=now && e_dtmf_last=='#')) /* when disconnected, just #. when dialing, ##. */
1950 /* dialing using dtmf digit */
1951 if (e_state==EPOINT_STATE_IN_OVERLAP)// && e_state==e_connectedmode)
1953 if (e_dialinginfo.id[0]=='\0' && !e_action)
1955 set_tone(portlist, "dialing");
1957 /* concat dialing string */
1958 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id))
1960 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1961 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1967 /* port MESSAGE_CRYPT */
1968 void EndpointAppPBX::port_crypt(struct port_list *portlist, int message_type, union parameter *param)
1970 /* send crypt response to cryptman */
1971 if (param->crypt.type == CR_MESSAGE_IND)
1972 cryptman_msg2man(param->crypt.data, param->crypt.len);
1974 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
1977 /* port MESSAGE_OVERLAP */
1978 void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, union parameter *param)
1980 struct message *message;
1982 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1984 /* signal to call tool */
1985 admin_call_response(e_adminid, ADMIN_CALL_SETUP_ACK, "", 0, 0, 0);
1987 if (e_dialing_queue[0] && portlist)
1989 /* send what we have not dialed yet, because we had no setup complete */
1990 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing pending digits: '%s'\n", ea_endpoint->ep_serial, e_dialing_queue);
1991 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
1992 SCPY(message->param.information.id, e_dialing_queue);
1993 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
1994 message_put(message);
1995 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
1996 e_dialing_queue[0] = '\0';
1998 /* check if pattern is available */
1999 if (!ea_endpoint->ep_portlist->next && portlist->early_b) /* one port_list relation and tones available */
2001 /* indicate patterns */
2002 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2003 message_put(message);
2005 /* connect audio, if not already */
2006 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2007 message->param.audiopath = CHANNEL_STATE_CONNECT;
2008 message_put(message);
2011 /* indicate no patterns */
2012 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
2013 message_put(message);
2015 /* disconnect audio, if not already */
2016 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2017 message->param.audiopath = CHANNEL_STATE_HOLD;
2018 message_put(message);
2020 new_state(EPOINT_STATE_OUT_OVERLAP);
2021 /* if we are in a join */
2022 if (ea_endpoint->ep_join_id)
2024 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2025 memcpy(&message->param, param, sizeof(union parameter));
2026 message_put(message);
2030 /* port MESSAGE_PROCEEDING */
2031 void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_type, union parameter *param)
2033 struct message *message;
2035 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2037 /* signal to call tool */
2038 admin_call_response(e_adminid, ADMIN_CALL_PROCEEDING, "", 0, 0, 0);
2040 e_state = EPOINT_STATE_OUT_PROCEEDING;
2041 /* check if pattern is availatle */
2042 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
2044 /* indicate patterns */
2045 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2046 message_put(message);
2048 /* connect audio, if not already */
2049 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2050 message->param.audiopath = CHANNEL_STATE_CONNECT;
2051 message_put(message);
2054 /* indicate no patterns */
2055 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
2056 message_put(message);
2058 /* disconnect audio, if not already */
2059 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2060 message->param.audiopath = CHANNEL_STATE_HOLD;
2061 message_put(message);
2063 /* if we are in a call */
2064 if (ea_endpoint->ep_join_id)
2066 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2067 memcpy(&message->param, param, sizeof(union parameter));
2068 message_put(message);
2072 /* port MESSAGE_ALERTING */
2073 void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type, union parameter *param)
2075 struct message *message;
2077 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2079 /* signal to call tool */
2080 admin_call_response(e_adminid, ADMIN_CALL_ALERTING, "", 0, 0, 0);
2082 new_state(EPOINT_STATE_OUT_ALERTING);
2083 /* check if pattern is available */
2084 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
2086 /* indicate patterns */
2087 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2088 message_put(message);
2090 /* connect audio, if not already */
2091 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2092 message->param.audiopath = CHANNEL_STATE_CONNECT;
2093 message_put(message);
2096 /* indicate no patterns */
2097 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
2098 message_put(message);
2100 /* disconnect audio, if not already */
2101 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2102 message->param.audiopath = CHANNEL_STATE_HOLD;
2103 message_put(message);
2105 /* if we are in a call */
2106 if (ea_endpoint->ep_join_id)
2108 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2109 memcpy(&message->param, param, sizeof(union parameter));
2110 message_put(message);
2114 /* port MESSAGE_CONNECT */
2115 void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, union parameter *param)
2117 struct message *message;
2119 unsigned long port_id = portlist->port_id;
2120 struct port_list *tportlist;
2122 struct interface *interface;
2124 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2126 /* signal to call tool */
2127 admin_call_response(e_adminid, ADMIN_CALL_CONNECT, numberrize_callerinfo(param->connectinfo.id,param->connectinfo.ntype), 0, 0, 0);
2129 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_connectinfo));
2130 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (start)\n", ea_endpoint->ep_serial);
2131 while(ea_endpoint->ep_portlist->next) /* as long as we have at least two ports */
2133 tportlist = ea_endpoint->ep_portlist;
2134 if (tportlist->port_id == port_id) /* if the first portlist is the calling one, the second must be a different one */
2135 tportlist = tportlist->next;
2136 if (tportlist->port_id == port_id)
2137 FATAL("EPOINT(%d) this should not happen since the portlist list must not have two links to the same port - exitting.\n");
2138 message = message_create(ea_endpoint->ep_serial, tportlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2139 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
2140 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2141 message_put(message);
2142 logmessage(message->type, &message->param, tportlist->port_id, DIRECTION_OUT);
2143 ea_endpoint->free_portlist(tportlist);
2145 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (end)\n", ea_endpoint->ep_serial);
2149 /* screen incoming connected id */
2150 interface = interface_first;
2153 if (!strcmp(e_connectinfo.interface, interface->name))
2157 interface = interface->next;
2160 screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface);
2162 /* screen connected name */
2164 SCPY(e_connectinfo.name, e_ext.name);
2166 /* add internal id to colp */
2167 SCPY(e_connectinfo.extension, e_ext.number);
2169 /* we store the connected port number */
2170 SCPY(e_extension_interface, e_connectinfo.interface);
2172 /* for internal and am calls, we get the extension's id */
2173 if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE)
2175 SCPY(e_connectinfo.id, e_ext.callerid);
2176 SCPY(e_connectinfo.extension, e_ext.number);
2177 e_connectinfo.itype = INFO_ITYPE_ISDN_EXTENSION;
2178 e_connectinfo.ntype = e_ext.callerid_type;
2179 e_connectinfo.present = e_ext.callerid_present;
2181 if (portlist->port_type==PORT_TYPE_VBOX_OUT)
2183 e_connectinfo.itype = INFO_ITYPE_VBOX;
2184 e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2187 new_state(EPOINT_STATE_CONNECT);
2189 /* set volume of rx and tx */
2190 if (e_ext.txvol!=256 || e_ext.rxvol!=256)
2192 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2193 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2194 message->param.mISDNsignal.rxvol = e_ext.txvol;
2195 message->param.mISDNsignal.txvol = e_ext.rxvol;
2196 message_put(message);
2199 e_cfnr_call = e_cfnr_release = 0;
2200 if (e_ext.number[0])
2201 e_dtmf = 1; /* allow dtmf */
2204 /* other calls with no caller id (or not available for the extension) and force colp */
2205 if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE)
2207 e_connectinfo.present = INFO_PRESENT_NOTAVAIL;
2208 if (portlist->port_type==PORT_TYPE_DSS1_TE_OUT || portlist->port_type==PORT_TYPE_DSS1_NT_OUT) /* external extension answered */
2210 port = find_port_id(portlist->port_id);
2213 SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.id, &e_connectinfo.ntype));
2214 e_connectinfo.present = INFO_PRESENT_ALLOWED;
2219 /* send connect to join */
2220 if (ea_endpoint->ep_join_id)
2222 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2223 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
2224 message_put(message);
2226 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2227 message->param.audiopath = CHANNEL_STATE_CONNECT;
2228 message_put(message);
2229 } else if (!e_adminid)
2232 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have a callback, so we create a call with cbcaller: \"%s\".\n", ea_endpoint->ep_serial, e_cbcaller);
2233 SCPY(e_ext.number, e_cbcaller);
2234 new_state(EPOINT_STATE_IN_OVERLAP);
2235 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) callback from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2237 /* get extension's info about terminal */
2238 if (!read_extension(&e_ext, e_ext.number))
2240 /* extension doesn't exist */
2241 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2242 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
2243 new_state(EPOINT_STATE_OUT_DISCONNECT);
2244 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
2248 /* put prefix in front of e_cbdialing */
2249 SPRINT(buffer, "%s%s", e_ext.prefix, e_cbdialing);
2250 SCPY(e_dialinginfo.id, buffer);
2251 e_dialinginfo.itype = INFO_ITYPE_ISDN;
2252 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
2254 /* use caller id (or if exist: id_next_call) for this call */
2255 e_callerinfo.screen = INFO_SCREEN_NETWORK;
2256 SCPY(e_callerinfo.extension, e_ext.number);
2257 if (e_ext.id_next_call_present >= 0)
2259 SCPY(e_callerinfo.id, e_ext.id_next_call);
2260 e_callerinfo.present = e_ext.id_next_call_present;
2261 e_callerinfo.ntype = e_ext.id_next_call_type;
2262 e_ext.id_next_call_present = -1;
2263 /* extension is written */
2264 write_extension(&e_ext, e_ext.number);
2267 SCPY(e_callerinfo.id, e_ext.callerid);
2268 e_callerinfo.present = e_ext.callerid_present;
2269 e_callerinfo.ntype = e_ext.callerid_type;
2272 e_connectedmode = 1; /* dtmf-hangup & disconnect prevention */
2275 /* check if caller id is NOT authenticated */
2276 if (!parse_callbackauth(e_ext.number, &e_callbackinfo))
2278 /* make call state to enter password */
2279 new_state(EPOINT_STATE_IN_OVERLAP);
2280 e_action = &action_password_write;
2281 e_match_timeout = 0;
2282 e_match_to_action = NULL;
2283 e_dialinginfo.id[0] = '\0';
2284 e_extdialing = strchr(e_dialinginfo.id, '\0');
2285 e_password_timeout = now+20;
2289 /* incoming call (callback) */
2290 e_ruleset = ruleset_main;
2292 e_rule = e_ruleset->rule_first;
2294 e_extdialing = e_dialinginfo.id;
2295 if (e_dialinginfo.id[0])
2297 set_tone(portlist, "dialing");
2301 set_tone(portlist, "dialpbx");
2304 } else /* testcall */
2306 set_tone(portlist, "hold");
2309 /* start recording if enabled, not when answering machine answers */
2310 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))
2312 /* check if we are a terminal */
2313 if (e_ext.number[0] == '\0')
2314 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
2317 port = find_port_id(portlist->port_id);
2319 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
2324 /* port MESSAGE_DISCONNECT MESSAGE_RELEASE */
2325 void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
2327 struct message *message;
2329 unsigned long port_id = portlist->port_id;
2333 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2335 /* signal to call tool */
2336 admin_call_response(e_adminid, (message_type==MESSAGE_DISCONNECT)?ADMIN_CALL_DISCONNECT:ADMIN_CALL_RELEASE, "", param->disconnectinfo.cause, param->disconnectinfo.location, 0);
2338 //#warning does this work? only disconnect when incoming port hat not already disconnected yet?
2339 if (e_state==EPOINT_STATE_IN_DISCONNECT && message_type!=MESSAGE_RELEASE)// || e_state==EPOINT_STATE_OUT_DISCONNECT || e_state==EPOINT_STATE_IDLE)
2341 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are already disconnected.\n", ea_endpoint->ep_serial);
2346 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);
2347 collect_cause(&e_multipoint_cause, &e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location);
2348 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new multipoint cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location);
2350 /* check if we have more than one portlist relation and we just ignore the disconnect */
2351 if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist->next)
2353 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the disconnect was from a multipoint call. we just release that relation.\n", ea_endpoint->ep_serial);
2354 portlist = ea_endpoint->ep_portlist;
2357 if (portlist->port_id == port_id)
2359 portlist = portlist->next;
2362 FATAL("EPOINT(%d) no portlist related to the calling port.\n", ea_endpoint->ep_serial);
2363 if (message_type != MESSAGE_RELEASE)
2365 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2366 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2367 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2368 message_put(message);
2369 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2371 ea_endpoint->free_portlist(portlist);
2372 return; /* one relation removed */
2374 if (e_state == EPOINT_STATE_CONNECT)
2376 /* use cause from port after connect */
2377 cause = param->disconnectinfo.cause;
2378 location = param->disconnectinfo.location;
2381 /* use multipoint cause if no connect yet */
2382 if (e_multipoint_cause)
2384 cause = e_multipoint_cause;
2385 location = e_multipoint_location;
2388 cause = CAUSE_NOUSER;
2389 location = LOCATION_PRIVATE_LOCAL;
2393 e_cfnr_call = e_cfnr_release = 0;
2395 /* process hangup */
2396 process_hangup(e_join_cause, e_join_location);
2397 e_multipoint_cause = 0;
2398 e_multipoint_location = 0;
2400 if (message_type == MESSAGE_DISCONNECT)
2402 /* tone to disconnected end */
2403 SPRINT(buffer, "cause_%02x", cause);
2404 if (ea_endpoint->ep_portlist)
2405 set_tone(ea_endpoint->ep_portlist, buffer);
2407 new_state(EPOINT_STATE_IN_DISCONNECT);
2410 if (ea_endpoint->ep_join_id)
2412 int haspatterns = 0;
2413 /* check if pattern is available */
2414 if (ea_endpoint->ep_portlist)
2415 if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->early_b)
2416 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
2417 && message_type != MESSAGE_RELEASE) // if we release, we are done
2421 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has patterns.\n", ea_endpoint->ep_serial);
2422 /* indicate patterns */
2423 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2424 message_put(message);
2425 /* connect audio, if not already */
2426 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2427 message->param.audiopath = CHANNEL_STATE_CONNECT;
2428 message_put(message);
2429 /* send disconnect */
2430 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2431 memcpy(&message->param, param, sizeof(union parameter));
2432 message_put(message);
2433 /* disable encryption if disconnected */
2434 //PERROR("REMOVE ME: state =%d, %d\n", e_crypt_state, e_crypt);
2436 cryptman_message(CI_DISCONNECT_IND, NULL, 0);
2440 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
2443 if (message_type == MESSAGE_RELEASE)
2444 ea_endpoint->free_portlist(portlist);
2445 release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, callcause, portcause */
2446 return; /* must exit here */
2449 /* port MESSAGE_TIMEOUT */
2450 void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type, union parameter *param)
2454 trace_header("TIMEOUT", DIRECTION_IN);
2455 message_type = MESSAGE_DISCONNECT;
2456 switch (param->state)
2458 case PORT_STATE_OUT_SETUP:
2459 case PORT_STATE_OUT_OVERLAP:
2460 add_trace("state", NULL, "outgoing setup/dialing");
2462 /* no user responding */
2463 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2464 return; /* must exit here */
2466 case PORT_STATE_IN_SETUP:
2467 case PORT_STATE_IN_OVERLAP:
2468 add_trace("state", NULL, "incoming setup/dialing");
2469 param->disconnectinfo.cause = CAUSE_INVALID; /* number incomplete */
2470 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2473 case PORT_STATE_OUT_PROCEEDING:
2474 add_trace("state", NULL, "outgoing proceeding");
2476 param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
2477 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2478 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2479 return; /* must exit here */
2481 case PORT_STATE_IN_PROCEEDING:
2482 add_trace("state", NULL, "incoming proceeding");
2483 param->disconnectinfo.cause = CAUSE_NOUSER;
2484 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL; /* no user responding */
2487 case PORT_STATE_OUT_ALERTING:
2488 add_trace("state", NULL, "outgoing alerting");
2490 param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
2491 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2492 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2493 return; /* must exit here */
2495 case PORT_STATE_CONNECT:
2496 add_trace("state", NULL, "connect");
2498 param->disconnectinfo.cause = CAUSE_NORMAL; /* normal */
2499 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2500 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2501 return; /* must exit here */
2503 case PORT_STATE_IN_ALERTING:
2504 add_trace("state", NULL, "incoming alerting");
2505 param->disconnectinfo.cause = CAUSE_NOANSWER;
2506 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2509 case PORT_STATE_IN_DISCONNECT:
2510 case PORT_STATE_OUT_DISCONNECT:
2511 add_trace("state", NULL, "disconnect");
2513 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
2514 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2515 return; /* must exit here */
2518 param->disconnectinfo.cause = 31; /* normal unspecified */
2519 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2522 /* release call, disconnect isdn */
2524 new_state(EPOINT_STATE_OUT_DISCONNECT);
2525 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2526 SCPY(e_tone, cause);
2529 set_tone(portlist, cause);
2530 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2531 portlist = portlist->next;
2533 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
2536 /* port MESSAGE_NOTIFY */
2537 void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, union parameter *param)
2539 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2541 struct message *message;
2545 /* signal to call tool */
2546 admin_call_response(e_adminid, ADMIN_CALL_NOTIFY, numberrize_callerinfo(param->notifyinfo.id,param->notifyinfo.ntype), 0, 0, param->notifyinfo.notify);
2547 if (param->notifyinfo.notify)
2549 e_rx_state = track_notify(e_rx_state, param->notifyinfo.notify);
2552 /* if we get notification from stack, local shows if we disabled/enabled audio stream */
2553 if (param->notifyinfo.local) switch(param->notifyinfo.notify)
2555 case INFO_NOTIFY_REMOTE_HOLD:
2556 case INFO_NOTIFY_USER_SUSPENDED:
2557 /* tell call about it */
2558 if (ea_endpoint->ep_join_id)
2560 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2561 message->param.audiopath = CHANNEL_STATE_HOLD;
2562 message_put(message);
2566 case INFO_NOTIFY_REMOTE_RETRIEVAL:
2567 case INFO_NOTIFY_USER_RESUMED:
2568 /* set volume of rx and tx */
2569 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
2570 if (e_ext.txvol!=256 || e_ext.rxvol!=256)
2573 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2574 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2575 message->param.mISDNsignal.rxvol = e_ext.txvol;
2576 message->param.mISDNsignal.txvol = e_ext.rxvol;
2577 message_put(message);
2579 /* set current tone */
2581 set_tone(portlist, e_tone);
2582 /* tell call about it */
2583 if (ea_endpoint->ep_join_id)
2585 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2586 message->param.audiopath = CHANNEL_STATE_CONNECT;
2587 message_put(message);
2592 /* get name of notify */
2593 switch(param->notifyinfo.notify)
2599 logtext = "USER_SUSPENDED";
2602 logtext = "BEARER_SERVICE_CHANGED";
2605 logtext = "USER_RESUMED";
2608 logtext = "CONFERENCE_ESTABLISHED";
2611 logtext = "CONFERENCE_DISCONNECTED";
2614 logtext = "OTHER_PARTY_ADDED";
2617 logtext = "ISOLATED";
2620 logtext = "REATTACHED";
2623 logtext = "OTHER_PARTY_ISOLATED";
2626 logtext = "OTHER_PARTY_REATTACHED";
2629 logtext = "OTHER_PARTY_SPLIT";
2632 logtext = "OTHER_PARTY_DISCONNECTED";
2635 logtext = "CONFERENCE_FLOATING";
2638 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
2641 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
2644 logtext = "CALL_IS_A_WAITING_CALL";
2647 logtext = "DIVERSION_ACTIVATED";
2650 logtext = "RESERVED_CT_1";
2653 logtext = "RESERVED_CT_2";
2656 logtext = "REVERSE_CHARGING";
2659 logtext = "REMOTE_HOLD";
2662 logtext = "REMOTE_RETRIEVAL";
2665 logtext = "CALL_IS_DIVERTING";
2668 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
2673 /* notify call if available */
2674 if (ea_endpoint->ep_join_id)
2676 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOTIFY);
2677 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
2678 message_put(message);
2683 /* port MESSAGE_FACILITY */
2684 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
2686 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2688 struct message *message;
2690 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_FACILITY);
2691 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2692 message_put(message);
2695 /* port MESSAGE_SUSPEND */
2696 /* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
2697 void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
2699 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2701 /* epoint is now parked */
2702 ea_endpoint->ep_park = 1;
2703 memcpy(ea_endpoint->ep_park_callid, param->parkinfo.callid, sizeof(ea_endpoint->ep_park_callid));
2704 ea_endpoint->ep_park_len = (param->parkinfo.len>8)?8:param->parkinfo.len;
2706 /* remove port relation */
2707 ea_endpoint->free_portlist(portlist);
2710 /* port MESSAGE_RESUME */
2711 /* NOTE: before resume, the active-notification must be done in order to set call mixer */
2712 void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
2714 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2716 /* epoint is now resumed */
2717 ea_endpoint->ep_park = 0;
2722 /* port sends message to the endpoint
2724 void EndpointAppPBX::ea_message_port(unsigned long port_id, int message_type, union parameter *param)
2726 struct port_list *portlist;
2727 struct message *message;
2729 portlist = ea_endpoint->ep_portlist;
2732 if (port_id == portlist->port_id)
2734 portlist = portlist->next;
2738 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);
2742 // PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
2743 switch(message_type)
2745 case MESSAGE_DATA: /* data from port */
2746 /* check if there is a call */
2747 if (!ea_endpoint->ep_join_id)
2749 /* continue if only one portlist */
2750 if (ea_endpoint->ep_portlist->next != NULL)
2752 /* forward message */
2753 message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2756 case MESSAGE_TONE_EOF: /* tone is end of file */
2757 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
2760 if (e_action->index == ACTION_VBOX_PLAY)
2764 if (e_action->index == ACTION_EFI)
2771 case MESSAGE_TONE_COUNTER: /* counter info received */
2772 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);
2774 if (e_action->index == ACTION_VBOX_PLAY)
2776 e_vbox_counter = param->counter.current;
2777 if (param->counter.max >= 0)
2778 e_vbox_counter_max = param->counter.max;
2782 /* PORT sends SETUP message */
2784 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);
2785 if (e_state!=EPOINT_STATE_IDLE)
2787 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
2790 port_setup(portlist, message_type, param);
2793 /* PORT sends INFORMATION message */
2794 case MESSAGE_INFORMATION: /* additional digits received */
2795 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);
2796 port_information(portlist, message_type, param);
2799 /* PORT sends FACILITY message */
2800 case MESSAGE_FACILITY:
2801 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2802 port_facility(portlist, message_type, param);
2805 /* PORT sends DTMF message */
2806 case MESSAGE_DTMF: /* dtmf digits received */
2807 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);
2808 port_dtmf(portlist, message_type, param);
2811 /* PORT sends CRYPT message */
2812 case MESSAGE_CRYPT: /* crypt response received */
2813 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) crypt response=%d\n", ea_endpoint->ep_serial, param->crypt.type);
2814 port_crypt(portlist, message_type, param);
2817 /* PORT sends MORE message */
2818 case MESSAGE_OVERLAP:
2819 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);
2820 if (e_state != EPOINT_STATE_OUT_SETUP)
2822 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);
2825 port_overlap(portlist, message_type, param);
2828 /* PORT sends PROCEEDING message */
2829 case MESSAGE_PROCEEDING: /* port is proceeding */
2830 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);
2831 if (e_state!=EPOINT_STATE_OUT_SETUP
2832 && e_state!=EPOINT_STATE_OUT_OVERLAP)
2834 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);
2837 port_proceeding(portlist, message_type, param);
2840 /* PORT sends ALERTING message */
2841 case MESSAGE_ALERTING:
2842 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);
2843 if (e_state!=EPOINT_STATE_OUT_SETUP
2844 && e_state!=EPOINT_STATE_OUT_OVERLAP
2845 && e_state!=EPOINT_STATE_OUT_PROCEEDING)
2847 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);
2850 port_alerting(portlist, message_type, param);
2853 /* PORT sends CONNECT message */
2854 case MESSAGE_CONNECT:
2855 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);
2856 if (e_state!=EPOINT_STATE_OUT_SETUP
2857 && e_state!=EPOINT_STATE_OUT_OVERLAP
2858 && e_state!=EPOINT_STATE_OUT_PROCEEDING
2859 && e_state!=EPOINT_STATE_OUT_ALERTING)
2861 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
2864 port_connect(portlist, message_type, param);
2867 /* PORT sends DISCONNECT message */
2868 case MESSAGE_DISCONNECT: /* port is disconnected */
2869 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);
2870 port_disconnect_release(portlist, message_type, param);
2873 /* PORT sends a RELEASE message */
2874 case MESSAGE_RELEASE: /* port releases */
2875 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);
2876 /* portlist is release at port_disconnect_release, thanx Paul */
2877 port_disconnect_release(portlist, message_type, param);
2880 /* PORT sends a TIMEOUT message */
2881 case MESSAGE_TIMEOUT:
2882 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);
2883 port_timeout(portlist, message_type, param);
2884 break; /* release */
2886 /* PORT sends a NOTIFY message */
2887 case MESSAGE_NOTIFY:
2888 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);
2889 port_notify(portlist, message_type, param);
2892 /* PORT sends a SUSPEND message */
2893 case MESSAGE_SUSPEND:
2894 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);
2895 port_suspend(portlist, message_type, param);
2896 break; /* suspend */
2898 /* PORT sends a RESUME message */
2899 case MESSAGE_RESUME:
2900 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);
2901 port_resume(portlist, message_type, param);
2905 /* port assigns bchannel */
2906 case MESSAGE_BCHANNEL: /* bchannel assignment messafe */
2907 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);
2908 /* only one port is expected to be connected to bchannel */
2909 message = message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2910 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_IN);
2916 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);
2919 /* Note: this endpoint may be destroyed, so we MUST return */
2923 /* messages from join
2925 /* join MESSAGE_CRYPT */
2926 void EndpointAppPBX::join_crypt(struct port_list *portlist, int message_type, union parameter *param)
2928 switch(param->crypt.type)
2930 /* message from remote port to "crypt manager" */
2931 case CU_ACTK_REQ: /* activate key-exchange */
2932 case CU_ACTS_REQ: /* activate shared key */
2933 case CU_DACT_REQ: /* deactivate */
2934 case CU_INFO_REQ: /* request last info message */
2935 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2938 /* message from "crypt manager" to user */
2939 case CU_ACTK_CONF: /* key-echange done */
2940 case CU_ACTS_CONF: /* shared key done */
2941 case CU_DACT_CONF: /* deactivated */
2942 case CU_DACT_IND: /* deactivated */
2943 case CU_ERROR_IND: /* receive error message */
2944 case CU_INFO_IND: /* receive info message */
2945 case CU_INFO_CONF: /* receive info message */
2946 encrypt_result(param->crypt.type, (char *)param->crypt.data);
2950 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);
2954 /* join MESSAGE_INFORMATION */
2955 void EndpointAppPBX::join_information(struct port_list *portlist, int message_type, union parameter *param)
2957 struct message *message;
2963 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2964 memcpy(&message->param.information, ¶m->information, sizeof(struct dialing_info));
2965 message_put(message);
2966 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2967 portlist = portlist->next;
2971 /* join MESSAGE_FACILITY */
2972 void EndpointAppPBX::join_facility(struct port_list *portlist, int message_type, union parameter *param)
2974 struct message *message;
2976 if (!e_ext.facility)
2983 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_FACILITY);
2984 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2985 message_put(message);
2986 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2987 portlist = portlist->next;
2991 /* join MESSAGE_MORE */
2992 void EndpointAppPBX::join_overlap(struct port_list *portlist, int message_type, union parameter *param)
2994 struct message *message;
2996 new_state(EPOINT_STATE_IN_OVERLAP);
2999 if (e_join_pattern && e_ext.own_setup)
3001 /* disconnect audio */
3002 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3003 message->param.audiopath = CHANNEL_STATE_HOLD;
3004 message_put(message);
3006 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
3008 set_tone(portlist, "dialtone");
3011 if (e_ext.number[0])
3012 set_tone(portlist, "dialpbx");
3014 set_tone(portlist, "dialtone");
3017 /* join MESSAGE_PROCEEDING */
3018 void EndpointAppPBX::join_proceeding(struct port_list *portlist, int message_type, union parameter *param)
3020 struct message *message;
3022 new_state(EPOINT_STATE_IN_PROCEEDING);
3024 /* own proceeding tone */
3027 /* connect / disconnect audio */
3028 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3029 if (e_ext.own_proceeding)
3030 message->param.audiopath = CHANNEL_STATE_HOLD;
3032 message->param.audiopath = CHANNEL_STATE_CONNECT;
3033 message_put(message);
3035 // UCPY(e_join_tone, "proceeding");
3038 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3039 message_put(message);
3040 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3042 set_tone(portlist, "proceeding");
3045 /* join MESSAGE_ALERTING */
3046 void EndpointAppPBX::join_alerting(struct port_list *portlist, int message_type, union parameter *param)
3048 struct message *message;
3050 new_state(EPOINT_STATE_IN_ALERTING);
3052 /* own alerting tone */
3055 /* connect / disconnect audio */
3056 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3057 if (e_ext.own_alerting)
3058 message->param.audiopath = CHANNEL_STATE_HOLD;
3060 message->param.audiopath = CHANNEL_STATE_CONNECT;
3061 message_put(message);
3065 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
3066 message_put(message);
3067 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3069 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
3071 set_tone(portlist, "ringing");
3074 if (e_ext.number[0])
3075 set_tone(portlist, "ringpbx");
3077 set_tone(portlist, "ringing");
3080 /* join MESSAGE_CONNECT */
3081 void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type, union parameter *param)
3083 struct message *message;
3084 struct interface *interface;
3086 new_state(EPOINT_STATE_CONNECT);
3087 // UCPY(e_join_tone, "");
3088 if (e_ext.number[0])
3089 e_dtmf = 1; /* allow dtmf */
3091 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_callerinfo));
3094 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3095 memcpy(&message->param, param, sizeof(union parameter));
3096 /* screen incoming caller id */
3097 interface = interface_first;
3100 if (!strcmp(e_connectinfo.interface, interface->name))
3104 interface = interface->next;
3107 screen(1, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface);
3108 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(e_connectinfo));
3110 /* screen clip if prefix is required */
3111 if (e_ext.number[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0])
3113 SCPY(message->param.connectinfo.id, e_ext.clip_prefix);
3114 SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype));
3115 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
3118 /* use internal caller id */
3119 if (e_ext.number[0] && e_connectinfo.extension[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
3121 SCPY(message->param.connectinfo.id, e_connectinfo.extension);
3122 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
3125 /* handle restricted caller ids */
3126 apply_callerid_restriction(e_ext.anon_ignore, message->param.connectinfo.id, &message->param.connectinfo.ntype, &message->param.connectinfo.present, &message->param.connectinfo.screen, message->param.connectinfo.extension, message->param.connectinfo.name);
3127 /* display callerid if desired for extension */
3128 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));
3130 /* use conp, if enabld */
3132 message->param.connectinfo.name[0] = '\0';
3135 message_put(message);
3136 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3138 set_tone(portlist, NULL);
3140 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3141 message->param.audiopath = CHANNEL_STATE_CONNECT;
3142 message_put(message);
3146 /* join MESSAGE_DISCONNECT MESSAGE_RELEASE */
3147 void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *param)
3150 struct message *message;
3151 struct port_list *portlist = NULL;
3154 /* be sure that we are active */
3156 e_tx_state = NOTIFY_STATE_ACTIVE;
3158 /* we are powerdialing, if e_powerdialing is set and limit is not exceeded if given */
3159 if (e_powerdialing && ((e_powercount+1)<e_powerlimit || e_powerlimit<1))
3161 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
3163 /* set time for power dialing */
3164 e_powerdialing = now_d + e_powerdelay; /* set redial in the future */
3167 /* set redial tone */
3168 if (ea_endpoint->ep_portlist)
3172 set_tone(ea_endpoint->ep_portlist, "redial");
3173 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);
3174 /* send proceeding when powerdialing and still setup (avoid dialing timeout) */
3175 if (e_state==EPOINT_STATE_IN_OVERLAP)
3177 new_state(EPOINT_STATE_IN_PROCEEDING);
3178 if (ea_endpoint->ep_portlist)
3180 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3181 message_put(message);
3182 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3184 /* caused the error, that the first knock sound was not there */
3185 /* set_tone(portlist, "proceeding"); */
3187 /* send display of powerdialing */
3188 if (e_ext.display_dialing)
3190 portlist = ea_endpoint->ep_portlist;
3193 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3195 SPRINT(message->param.notifyinfo.display, "Retry %d of %d", e_powercount, e_powerlimit);
3197 SPRINT(message->param.notifyinfo.display, "Retry %d", e_powercount);
3198 message_put(message);
3199 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3200 portlist = portlist->next;
3209 if ((e_state!=EPOINT_STATE_CONNECT
3210 && e_state!=EPOINT_STATE_OUT_DISCONNECT
3211 && e_state!=EPOINT_STATE_IN_OVERLAP
3212 && e_state!=EPOINT_STATE_IN_PROCEEDING
3213 && e_state!=EPOINT_STATE_IN_ALERTING)
3214 || !ea_endpoint->ep_portlist) /* or no port */
3216 process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
3217 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause); /* RELEASE_TYPE, join, port */
3218 return; /* must exit here */
3223 e_join_cause = param->disconnectinfo.cause;
3224 e_join_location = param->disconnectinfo.location;
3227 /* on release we need the audio again! */
3228 if (message_type == MESSAGE_RELEASE)
3231 ea_endpoint->ep_join_id = 0;
3233 /* disconnect and select tone */
3234 new_state(EPOINT_STATE_OUT_DISCONNECT);
3235 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
3236 /* if own_cause, we must release the join */
3237 if (e_ext.own_cause /* own cause */
3238 || !e_join_pattern) /* no patterns */
3240 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);
3241 if (message_type != MESSAGE_RELEASE)
3242 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
3244 } else /* else we enable audio */
3246 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3247 message->param.audiopath = CHANNEL_STATE_CONNECT;
3248 message_put(message);
3250 /* send disconnect message */
3251 SCPY(e_tone, cause);
3252 portlist = ea_endpoint->ep_portlist;
3255 set_tone(portlist, cause);
3256 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
3257 portlist = portlist->next;
3261 /* join MESSAGE_SETUP */
3262 void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, union parameter *param)
3264 struct message *message;
3265 struct interface *interface;
3267 /* if we already in setup state, we just update the dialing with new digits */
3268 if (e_state == EPOINT_STATE_OUT_SETUP
3269 || e_state == EPOINT_STATE_OUT_OVERLAP)
3271 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we are in setup state, so we do overlap dialing.\n", ea_endpoint->ep_serial);
3272 /* if digits changed, what we have already dialed */
3273 if (!!strncmp(e_dialinginfo.id,param->setup.dialinginfo.id,strlen(e_dialinginfo.id)))
3275 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);
3276 /* release all ports */
3277 while((portlist = ea_endpoint->ep_portlist))
3279 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
3280 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
3281 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3282 message_put(message);
3283 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3284 ea_endpoint->free_portlist(portlist);
3287 /* disconnect audio */
3288 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3289 message->param.audiopath = CHANNEL_STATE_HOLD;
3290 message_put(message);
3292 /* get dialing info */
3293 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3294 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3295 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3296 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3297 new_state(EPOINT_STATE_OUT_OVERLAP);
3300 e_redial = now_d + 1; /* set redial one second in the future */
3303 /* if we have a pending redial, so we just adjust the dialing number */
3306 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);
3307 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3310 if (!ea_endpoint->ep_portlist)
3312 PERROR("ERROR: overlap dialing to a NULL port relation\n");
3314 if (ea_endpoint->ep_portlist->next)
3316 PERROR("ERROR: overlap dialing to a port_list port relation\n");
3318 if (e_state == EPOINT_STATE_OUT_SETUP)
3321 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);
3322 SCAT(e_dialing_queue, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3326 /* get what we have not dialed yet */
3327 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));
3328 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
3329 SCPY(message->param.information.id, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3330 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
3331 message_put(message);
3332 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3334 /* always store what we have dialed or queued */
3335 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3339 if (e_state != EPOINT_STATE_IDLE)
3341 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
3344 /* if an internal extension is dialed, copy that number */
3345 if (param->setup.dialinginfo.itype==INFO_ITYPE_ISDN_EXTENSION || param->setup.dialinginfo.itype==INFO_ITYPE_VBOX)
3346 SCPY(e_ext.number, param->setup.dialinginfo.id);
3347 /* if an internal extension is dialed, get extension's info about caller */
3348 if (e_ext.number[0])
3350 if (!read_extension(&e_ext, e_ext.number))
3352 e_ext.number[0] = '\0';
3353 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the called terminal='%s' is not found in directory tree!\n", ea_endpoint->ep_serial, e_ext.number);
3357 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3358 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3359 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3360 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3362 /* screen incoming caller id */
3363 interface = interface_first;
3366 if (!strcmp(e_callerinfo.interface, interface->name))
3370 interface = interface->next;
3373 screen(1, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface);
3375 /* process (voice over) data calls */
3376 if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO)
3378 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) handling data call as audio call: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
3379 memset(&e_capainfo, 0, sizeof(e_capainfo));
3380 e_capainfo.bearer_capa = INFO_BC_AUDIO;
3381 e_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
3382 e_capainfo.bearer_info1 = (options.law=='u')?INFO_INFO1_ULAW:INFO_INFO1_ALAW;
3385 new_state(EPOINT_STATE_OUT_SETUP);
3386 /* call special setup routine */
3390 /* join MESSAGE_mISDNSIGNAL */
3391 void EndpointAppPBX::join_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param)
3393 struct message *message;
3397 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
3398 memcpy(&message->param, param, sizeof(union parameter));
3399 message_put(message);
3400 portlist = portlist->next;
3404 /* join MESSAGE_NOTIFY */
3405 void EndpointAppPBX::join_notify(struct port_list *portlist, int message_type, union parameter *param)
3407 struct message *message;
3410 if (param->notifyinfo.notify)
3412 new_state = track_notify(e_tx_state, param->notifyinfo.notify);
3413 // /* if notification was generated locally, we turn hold music on/off */
3414 // if (param->notifyinfo.local)
3415 // 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)
3420 if (new_state!=NOTIFY_STATE_HOLD && new_state!=NOTIFY_STATE_SUSPEND)
3424 set_tone(portlist, "");
3425 portlist = portlist->next;
3427 portlist = ea_endpoint->ep_portlist;
3432 if (new_state==NOTIFY_STATE_HOLD || new_state==NOTIFY_STATE_SUSPEND)
3436 set_tone(portlist, "hold");
3437 portlist = portlist->next;
3439 portlist = ea_endpoint->ep_portlist;
3444 /* save new state */
3445 e_tx_state = new_state;
3448 /* notify port(s) about it */
3451 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3452 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
3453 /* handle restricted caller ids */
3454 apply_callerid_restriction(e_ext.anon_ignore, message->param.notifyinfo.id, &message->param.notifyinfo.ntype, &message->param.notifyinfo.present, 0, message->param.notifyinfo.extension, NULL);
3455 /* display callerid if desired for extension */
3456 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));
3457 message_put(message);
3458 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3459 portlist = portlist->next;
3463 /* JOIN sends messages to the endpoint
3465 void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, union parameter *param)
3467 struct port_list *portlist;
3468 struct message *message;
3472 PERROR("EPOINT(%d) error: JOIN == NULL.\n", ea_endpoint->ep_serial);
3476 portlist = ea_endpoint->ep_portlist;
3478 /* send MESSAGE_DATA to port */
3479 if (message_type == MESSAGE_DATA)
3481 if (join_id == ea_endpoint->ep_join_id) // still linked with JOIN
3483 /* skip if no port relation */
3486 /* skip if more than one port relation */
3489 /* forward audio data to port */
3490 message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3495 // 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);
3496 switch(message_type)
3498 /* JOIN SENDS CRYPT message */
3500 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);
3501 join_crypt(portlist, message_type, param);
3504 /* JOIN sends INFORMATION message */
3505 case MESSAGE_INFORMATION:
3506 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);
3507 join_information(portlist, message_type, param);
3510 /* JOIN sends FACILITY message */
3511 case MESSAGE_FACILITY:
3512 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);
3513 join_facility(portlist, message_type, param);
3516 /* JOIN sends OVERLAP message */
3517 case MESSAGE_OVERLAP:
3518 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received 'more info available'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3519 if (e_state!=EPOINT_STATE_IN_SETUP
3520 && e_state!=EPOINT_STATE_IN_OVERLAP)
3522 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3525 join_overlap(portlist, message_type, param);
3528 /* JOIN sends PROCEEDING message */
3529 case MESSAGE_PROCEEDING:
3530 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);
3531 if(e_state!=EPOINT_STATE_IN_OVERLAP)
3533 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3536 join_proceeding(portlist, message_type, param);
3539 /* JOIN sends ALERTING message */
3540 case MESSAGE_ALERTING:
3541 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);
3542 if (e_state!=EPOINT_STATE_IN_OVERLAP
3543 && e_state!=EPOINT_STATE_IN_PROCEEDING)
3545 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state.\n", ea_endpoint->ep_serial);
3548 join_alerting(portlist, message_type, param);
3551 /* JOIN sends CONNECT message */
3552 case MESSAGE_CONNECT:
3553 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);
3554 if (e_state!=EPOINT_STATE_IN_OVERLAP
3555 && e_state!=EPOINT_STATE_IN_PROCEEDING
3556 && e_state!=EPOINT_STATE_IN_ALERTING)
3558 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
3561 join_connect(portlist, message_type, param);
3564 /* JOIN sends DISCONNECT/RELEASE message */
3565 case MESSAGE_DISCONNECT: /* JOIN disconnect */
3566 case MESSAGE_RELEASE: /* JOIN releases */
3567 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);
3568 join_disconnect_release(message_type, param);
3571 /* JOIN sends SETUP message */
3573 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);
3574 join_setup(portlist, message_type, param);
3577 /* JOIN sends special mISDNSIGNAL message */
3578 case MESSAGE_mISDNSIGNAL: /* isdn message to port */
3579 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);
3580 join_mISDNsignal(portlist, message_type, param);
3584 /* JOIN requests bchannel */
3585 case MESSAGE_BCHANNEL: /* indicates the need of own bchannel access */
3586 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);
3587 /* only one port is expected to be connected to bchannel */
3594 set_tone(portlist, NULL);
3595 message = message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3596 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3600 /* JOIN has pattern available */
3601 case MESSAGE_PATTERN: /* indicating pattern available */
3602 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);
3603 if (!e_join_pattern)
3605 PDEBUG(DEBUG_EPOINT, "-> pattern becomes available\n");
3610 set_tone(portlist, NULL);
3611 portlist = portlist->next;
3613 /* connect our audio tx and rx (blueboxing should be possibe before connect :)*/
3614 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3615 message->param.audiopath = CHANNEL_STATE_CONNECT;
3616 message_put(message);
3617 // /* tell remote epoint to connect audio also, because we like to hear the patterns */
3618 // message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_REMOTE_AUDIO);
3619 // message->param.audiopath = CHANNEL_STATE_CONNECT;
3620 // message_put(message);
3621 // patterns are available, remote already connected audio
3625 /* JOIN has no pattern available */
3626 case MESSAGE_NOPATTERN: /* indicating no pattern available */
3627 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);
3630 PDEBUG(DEBUG_EPOINT, "-> pattern becomes unavailable\n");
3632 /* disconnect our audio tx and rx */
3633 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3634 message->param.audiopath = CHANNEL_STATE_HOLD;
3635 message_put(message);
3640 /* JOIN (dunno at the moment) */
3641 case MESSAGE_REMOTE_AUDIO:
3642 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);
3643 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3644 message->param.audiopath = param->channel;
3645 message_put(message);
3649 /* JOIN sends a notify message */
3650 case MESSAGE_NOTIFY:
3651 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);
3652 join_notify(portlist, message_type, param);
3656 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);
3661 /* pick_join will connect the first incoming call found. the endpoint
3662 * will receivce a MESSAGE_CONNECT.
3664 int match_list(char *list, char *item)
3666 char *end, *next = NULL;
3668 /* no list make matching */
3674 /* eliminate white spaces */
3675 while (*list <= ' ')
3682 /* if end of list is reached, we return */
3683 if (list[0] == '\0')
3685 /* if we have more than one entry (left) */
3686 if ((end = strchr(list, ',')))
3689 next = end = strchr(list, '\0');
3690 while (*(end-1) <= ' ')
3692 /* if string part matches item */
3693 if (!strncmp(list, item, end-list))
3699 void EndpointAppPBX::pick_join(char *extensions)
3701 struct message *message;
3702 struct port_list *portlist;
3704 class EndpointAppPBX *eapp, *found;
3706 class JoinPBX *joinpbx;
3707 struct join_relation *relation;
3710 /* find an endpoint that is ringing internally or vbox with higher priority */
3713 eapp = apppbx_first;
3716 if (eapp!=this && ea_endpoint->ep_portlist)
3718 portlist = eapp->ea_endpoint->ep_portlist;
3721 if ((port = find_port_id(portlist->port_id)))
3723 if (port->p_type == PORT_TYPE_VBOX_OUT)
3725 if (match_list(extensions, eapp->e_ext.number))
3732 if ((port->p_type==PORT_TYPE_DSS1_NT_OUT || port->p_type==PORT_TYPE_DSS1_TE_OUT)
3733 && port->p_state==PORT_STATE_OUT_ALERTING)
3734 if (match_list(extensions, eapp->e_ext.number))
3739 portlist = portlist->next;
3747 /* if no endpoint found */
3750 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);
3752 set_tone(ea_endpoint->ep_portlist, "cause_10");
3753 message_disconnect_port(ea_endpoint->ep_portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
3754 new_state(EPOINT_STATE_OUT_DISCONNECT);
3759 if (ea_endpoint->ep_join_id)
3761 PERROR("EPOINT(%d) we already have a join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3764 if (!eapp->ea_endpoint->ep_join_id)
3766 PERROR("EPOINT(%d) ringing endpoint has no join.\n", ea_endpoint->ep_serial);
3769 join = find_join_id(eapp->ea_endpoint->ep_join_id);
3772 PERROR("EPOINT(%d) ringing endpoint's join not found.\n", ea_endpoint->ep_serial);
3775 if (join->j_type != JOIN_TYPE_PBX)
3777 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ringing endpoint's join is not a PBX join, so we must reject.\n", ea_endpoint->ep_serial);
3780 joinpbx = (class JoinPBX *)join;
3781 relation = joinpbx->j_relation;
3784 PERROR("EPOINT(%d) ringing endpoint's join has no relation. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3787 while (relation->epoint_id != eapp->ea_endpoint->ep_serial)
3789 relation = relation->next;
3792 PERROR("EPOINT(%d) ringing endpoint's join has no relation to that join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3797 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found ringing endpoint: %d.\n", ea_endpoint->ep_serial, eapp->ea_endpoint->ep_serial);
3799 if (options.deb & DEBUG_EPOINT)
3801 class Join *debug_c = join_first;
3802 class Endpoint *debug_e = epoint_first;
3803 class Port *debug_p = port_first;
3805 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(before)");
3807 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3810 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3811 debug_c = debug_c->next;
3813 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3816 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3817 debug_e = debug_e->next;
3819 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3822 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld (active)\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3823 debug_p = debug_p->next;
3828 ea_endpoint->ep_join_id = eapp->ea_endpoint->ep_join_id; /* we get the join */
3829 relation->epoint_id = ea_endpoint->ep_serial; /* the join gets us */
3830 eapp->ea_endpoint->ep_join_id = 0; /* the ringing endpoint will get disconnected */
3832 /* connnecting our endpoint */
3833 new_state(EPOINT_STATE_CONNECT);
3835 set_tone(ea_endpoint->ep_portlist, NULL);
3837 /* now we send a release to the ringing endpoint */
3838 message = message_create(ea_endpoint->ep_join_id, eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3839 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
3840 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3841 message_put(message);
3843 /* we send a connect to the join with our caller id */
3844 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CONNECT);
3845 SCPY(message->param.connectinfo.id, e_callerinfo.id);
3846 message->param.connectinfo.present = e_callerinfo.present;
3847 message->param.connectinfo.screen = e_callerinfo.screen;
3848 message->param.connectinfo.itype = e_callerinfo.itype;
3849 message->param.connectinfo.ntype = e_callerinfo.ntype;
3850 message_put(message);
3852 /* we send a connect to our port with the remote callerid */
3853 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3854 SCPY(message->param.connectinfo.id, eapp->e_callerinfo.id);
3855 message->param.connectinfo.present = eapp->e_callerinfo.present;
3856 message->param.connectinfo.screen = eapp->e_callerinfo.screen;
3857 message->param.connectinfo.itype = eapp->e_callerinfo.itype;
3858 message->param.connectinfo.ntype = eapp->e_callerinfo.ntype;
3859 /* handle restricted caller ids */
3860 apply_callerid_restriction(e_ext.anon_ignore, message->param.connectinfo.id, &message->param.connectinfo.ntype, &message->param.connectinfo.present, &message->param.connectinfo.screen, message->param.connectinfo.extension, message->param.connectinfo.name);
3861 /* display callerid if desired for extension */
3862 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));
3863 message_put(message);
3865 /* we send a connect to the audio path (not for vbox) */
3866 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3867 message->param.audiopath = CHANNEL_STATE_CONNECT;
3868 message_put(message);
3870 /* beeing paranoid, we make call update */
3871 joinpbx->j_updatebridge = 1;
3873 if (options.deb & DEBUG_EPOINT)
3875 class Join *debug_c = join_first;
3876 class Endpoint *debug_e = epoint_first;
3877 class Port *debug_p = port_first;
3879 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(after)");
3881 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3884 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3885 debug_c = debug_c->next;
3887 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3890 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3891 debug_e = debug_e->next;
3893 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3896 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3897 debug_p = debug_p->next;
3903 /* join calls (look for a join that is on hold (same isdn interface/terminal))
3905 void EndpointAppPBX::join_join(void)
3907 struct message *message;
3908 struct join_relation *our_relation, *other_relation;
3909 struct join_relation **our_relation_pointer, **other_relation_pointer;
3910 class Join *our_join, *other_join;
3911 class JoinPBX *our_joinpbx, *other_joinpbx;
3912 class EndpointAppPBX *other_eapp; class Endpoint *temp_epoint;
3913 class Port *our_port, *other_port;
3914 class Pdss1 *our_pdss1, *other_pdss1;
3916 /* are we a candidate to join a join */
3917 our_join = find_join_id(ea_endpoint->ep_join_id);
3920 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3923 if (our_join->j_type != JOIN_TYPE_PBX)
3925 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: join is not a pbx join.\n", ea_endpoint->ep_serial);
3928 our_joinpbx = (class JoinPBX *)our_join;
3929 if (!ea_endpoint->ep_portlist)
3931 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
3934 if (!e_ext.number[0])
3936 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
3939 our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
3942 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
3945 if ((our_port->p_type&PORT_CLASS_mISDN_MASK) != PORT_CLASS_mISDN_DSS1)
3947 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not isdn.\n", ea_endpoint->ep_serial);
3950 our_pdss1 = (class Pdss1 *)our_port;
3952 /* find an endpoint that is on hold and has the same mISDNport that we are on */
3953 other_eapp = apppbx_first;
3956 if (other_eapp == this)
3958 other_eapp = other_eapp->next;
3961 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);
3962 if (other_eapp->e_ext.number[0] /* has terminal */
3963 && other_eapp->ea_endpoint->ep_portlist /* has port */
3964 && other_eapp->ea_endpoint->ep_join_id) /* has join */
3966 other_port = find_port_id(other_eapp->ea_endpoint->ep_portlist->port_id);
3967 if (other_port) /* port still exists */
3969 if (other_port->p_type==PORT_TYPE_DSS1_NT_OUT
3970 || other_port->p_type==PORT_TYPE_DSS1_NT_IN) /* port is isdn nt-mode */
3972 other_pdss1 = (class Pdss1 *)other_port;
3973 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);
3974 if (other_pdss1->p_m_hold /* port is on hold */
3975 && other_pdss1->p_m_mISDNport == our_pdss1->p_m_mISDNport /* same isdn interface */
3976 && other_pdss1->p_m_d_ces == our_pdss1->p_m_d_ces) /* same tei+sapi */
3980 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of other type!\n", ea_endpoint->ep_serial);
3984 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port doesn't exist enymore.\n", ea_endpoint->ep_serial);
3987 other_eapp = other_eapp->next;
3991 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn interface with port on hold.\n", ea_endpoint->ep_serial);
3994 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port on hold found.\n", ea_endpoint->ep_serial);
3996 /* if we have the same join */
3997 if (other_eapp->ea_endpoint->ep_join_id == ea_endpoint->ep_join_id)
3999 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we an the other have the same join.\n", ea_endpoint->ep_serial);
4002 other_join = find_join_id(other_eapp->ea_endpoint->ep_join_id);
4005 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
4008 if (other_join->j_type != JOIN_TYPE_PBX)
4010 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join is not a pbx join.\n", ea_endpoint->ep_serial);
4013 other_joinpbx = (class JoinPBX *)other_join;
4014 if (our_joinpbx->j_partyline && other_joinpbx->j_partyline)
4016 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both joins are partylines.\n", ea_endpoint->ep_serial);
4020 /* remove relation to endpoint for join on hold */
4021 other_relation = other_joinpbx->j_relation;
4022 other_relation_pointer = &other_joinpbx->j_relation;
4023 while(other_relation)
4025 if (other_relation->epoint_id == other_eapp->ea_endpoint->ep_serial)
4027 /* detach other endpoint on hold */
4028 *other_relation_pointer = other_relation->next;
4029 FREE(other_relation, sizeof(struct join_relation));
4031 other_relation = *other_relation_pointer;
4032 other_eapp->ea_endpoint->ep_join_id = NULL;
4036 /* change join/hold pointer of endpoint to the new join */
4037 temp_epoint = find_epoint_id(other_relation->epoint_id);
4040 if (temp_epoint->ep_join_id == other_join->j_serial)
4041 temp_epoint->ep_join_id = our_join->j_serial;
4044 other_relation_pointer = &other_relation->next;
4045 other_relation = other_relation->next;
4047 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint on hold removed, other enpoints on join relinked (to our join).\n", ea_endpoint->ep_serial);
4049 /* join call relations */
4050 our_relation = our_joinpbx->j_relation;
4051 our_relation_pointer = &our_joinpbx->j_relation;
4054 our_relation_pointer = &our_relation->next;
4055 our_relation = our_relation->next;
4057 *our_relation_pointer = other_joinpbx->j_relation;
4058 other_joinpbx->j_relation = NULL;
4059 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) relations joined.\n", ea_endpoint->ep_serial);
4061 /* release endpoint on hold */
4062 message = message_create(other_joinpbx->j_serial, other_eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
4063 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */
4064 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
4065 message_put(message);
4067 /* if we are not a partyline, we get partyline state from other join */
4068 our_joinpbx->j_partyline += other_joinpbx->j_partyline;
4070 /* remove empty join */
4072 PDEBUG(DEBUG_EPOINT, "EPOINT(%d)d-join completely removed!\n");
4074 /* mixer must update */
4075 our_joinpbx->j_updatebridge = 1; /* update mixer flag */
4077 /* we send a retrieve to that endpoint */
4078 // mixer will update the hold-state of the join and send it to the endpoints is changes
4082 /* check if we have an external call
4083 * this is used to check for encryption ability
4085 int EndpointAppPBX::check_external(char **errstr, class Port **port)
4087 struct join_relation *relation;
4089 class JoinPBX *joinpbx;
4090 class Endpoint *epoint;
4092 /* some paranoia check */
4093 if (!ea_endpoint->ep_portlist)
4095 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we have no port.\n", ea_endpoint->ep_serial);
4096 *errstr = "No Call";
4099 if (!e_ext.number[0])
4101 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we are not internal extension.\n", ea_endpoint->ep_serial);
4102 *errstr = "No Call";
4106 /* check if we have a join with 2 parties */
4107 join = find_join_id(ea_endpoint->ep_join_id);
4110 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have currently no join.\n", ea_endpoint->ep_serial);
4111 *errstr = "No Call";
4114 if (join->j_type != JOIN_TYPE_PBX)
4116 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join is not a pbx join.\n", ea_endpoint->ep_serial);
4117 *errstr = "No PBX Call";
4120 joinpbx = (class JoinPBX *)join;
4121 relation = joinpbx->j_relation;
4124 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no relation.\n", ea_endpoint->ep_serial);
4125 *errstr = "No Call";
4128 if (!relation->next)
4130 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd relation.\n", ea_endpoint->ep_serial);
4131 *errstr = "No Call";
4134 if (relation->next->next)
4136 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has more than two relations.\n", ea_endpoint->ep_serial);
4137 *errstr = "Err: Conference";
4140 if (relation->epoint_id == ea_endpoint->ep_serial)
4142 relation = relation->next;
4143 if (relation->epoint_id == ea_endpoint->ep_serial)
4145 PERROR("EPOINT(%d) SOFTWARE ERROR: both join relations are related to our endpoint.\n", ea_endpoint->ep_serial);
4146 *errstr = "Software Error";
4151 /* check remote port for external call */
4152 epoint = find_epoint_id(relation->epoint_id);
4155 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd endpoint.\n", ea_endpoint->ep_serial);
4156 *errstr = "No Call";
4159 if (!epoint->ep_portlist)
4161 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not port.\n", ea_endpoint->ep_serial);
4162 *errstr = "No Call";
4165 *port = find_port_id(epoint->ep_portlist->port_id);
4168 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has an none existing port.\n", ea_endpoint->ep_serial);
4169 *errstr = "No Call";
4172 if (((*port)->p_type&PORT_CLASS_mISDN_MASK)!=PORT_CLASS_mISDN_DSS1) /* port is not external isdn */
4174 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not an external port.\n", ea_endpoint->ep_serial);
4175 *errstr = "No Ext Call";
4178 if ((*port)->p_state != PORT_STATE_CONNECT)
4180 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint's port is not in connected state.\n", ea_endpoint->ep_serial);
4181 *errstr = "No Ext Connect";
4187 void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsigned long port_id, int dir)
4189 char *logtext = "unknown";
4192 switch(message_type)
4195 trace_header("SETUP", dir);
4196 if (dir == DIRECTION_OUT)
4197 add_trace("to", NULL, "CH(%lu)", port_id);
4198 if (dir == DIRECTION_IN)
4199 add_trace("from", NULL, "CH(%lu)", port_id);
4200 if (param->setup.callerinfo.extension[0])
4201 add_trace("extension", NULL, "%s", param->setup.callerinfo.extension);
4202 add_trace("caller id", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype));
4203 switch(param->setup.callerinfo.present)
4205 case INFO_PRESENT_RESTRICTED:
4206 add_trace("caller id", "present", "restricted");
4208 case INFO_PRESENT_ALLOWED:
4209 add_trace("caller id", "present", "allowed");
4212 add_trace("caller id", "present", "not available");
4214 if (param->setup.redirinfo.id[0])
4216 add_trace("redir'ing", "number", "%s", numberrize_callerinfo(param->setup.redirinfo.id, param->setup.redirinfo.ntype));
4217 switch(param->setup.redirinfo.present)
4219 case INFO_PRESENT_RESTRICTED:
4220 add_trace("redir'ing", "present", "restricted");
4222 case INFO_PRESENT_ALLOWED:
4223 add_trace("redir'ing", "present", "allowed");
4226 add_trace("redir'ing", "present", "not available");
4229 if (param->setup.dialinginfo.id[0])
4230 add_trace("dialing", NULL, "%s", param->setup.dialinginfo.id);
4234 case MESSAGE_OVERLAP:
4235 trace_header("SETUP ACKNOWLEDGE", dir);
4236 if (dir == DIRECTION_OUT)
4237 add_trace("to", NULL, "CH(%lu)", port_id);
4238 if (dir == DIRECTION_IN)
4239 add_trace("from", NULL, "CH(%lu)", port_id);
4243 case MESSAGE_PROCEEDING:
4244 trace_header("PROCEEDING", dir);
4245 if (dir == DIRECTION_OUT)
4246 add_trace("to", NULL, "CH(%lu)", port_id);
4247 if (dir == DIRECTION_IN)
4248 add_trace("from", NULL, "CH(%lu)", port_id);
4252 case MESSAGE_ALERTING:
4253 trace_header("ALERTING", dir);
4254 if (dir == DIRECTION_OUT)
4255 add_trace("to", NULL, "CH(%lu)", port_id);
4256 if (dir == DIRECTION_IN)
4257 add_trace("from", NULL, "CH(%lu)", port_id);
4261 case MESSAGE_CONNECT:
4262 trace_header("CONNECT", dir);
4263 if (dir == DIRECTION_OUT)
4264 add_trace("to", NULL, "CH(%lu)", port_id);
4265 if (dir == DIRECTION_IN)
4266 add_trace("from", NULL, "CH(%lu)", port_id);
4267 if (param->connectinfo.extension[0])
4268 add_trace("extension", NULL, "%s", param->connectinfo.extension);
4269 add_trace("connect id", "number", "%s", numberrize_callerinfo(param->connectinfo.id, param->connectinfo.ntype));
4270 switch(param->connectinfo.present)
4272 case INFO_PRESENT_RESTRICTED:
4273 add_trace("connect id", "present", "restricted");
4275 case INFO_PRESENT_ALLOWED:
4276 add_trace("connect id", "present", "allowed");
4279 add_trace("connect id", "present", "not available");
4284 case MESSAGE_DISCONNECT:
4285 case MESSAGE_RELEASE:
4286 if (message_type == MESSAGE_DISCONNECT)
4287 trace_header("DISCONNECT", dir);
4289 trace_header("RELEASE", dir);
4290 if (dir == DIRECTION_OUT)
4291 add_trace("to", NULL, "CH(%lu)", port_id);
4292 if (dir == DIRECTION_IN)
4293 add_trace("from", NULL, "CH(%lu)", port_id);
4294 add_trace("cause", "value", "%d", param->disconnectinfo.cause);
4295 switch(param->disconnectinfo.location)
4298 add_trace("cause", "location", "0-User");
4300 case LOCATION_PRIVATE_LOCAL:
4301 add_trace("cause", "location", "1-Local-PBX");
4303 case LOCATION_PUBLIC_LOCAL:
4304 add_trace("cause", "location", "2-Local-Exchange");
4306 case LOCATION_TRANSIT:
4307 add_trace("cause", "location", "3-Transit");
4309 case LOCATION_PUBLIC_REMOTE:
4310 add_trace("cause", "location", "4-Remote-PBX");
4312 case LOCATION_PRIVATE_REMOTE:
4313 add_trace("cause", "location", "5-Remote-Exchange");
4315 case LOCATION_INTERNATIONAL:
4316 add_trace("cause", "location", "7-International-Exchange");
4318 case LOCATION_BEYOND:
4319 add_trace("cause", "location", "10-Beyond-Interworking");
4322 add_trace("cause", "location", "%d", param->disconnectinfo.location);
4327 case MESSAGE_NOTIFY:
4328 switch(param->notifyinfo.notify)
4334 logtext = "USER_SUSPENDED";
4337 logtext = "BEARER_SERVICE_CHANGED";
4340 logtext = "USER_RESUMED";
4343 logtext = "CONFERENCE_ESTABLISHED";
4346 logtext = "CONFERENCE_DISCONNECTED";
4349 logtext = "OTHER_PARTY_ADDED";
4352 logtext = "ISOLATED";
4355 logtext = "REATTACHED";
4358 logtext = "OTHER_PARTY_ISOLATED";
4361 logtext = "OTHER_PARTY_REATTACHED";
4364 logtext = "OTHER_PARTY_SPLIT";
4367 logtext = "OTHER_PARTY_DISCONNECTED";
4370 logtext = "CONFERENCE_FLOATING";
4373 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
4376 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
4379 logtext = "CALL_IS_A_WAITING_CALL";
4382 logtext = "DIVERSION_ACTIVATED";
4385 logtext = "RESERVED_CT_1";
4388 logtext = "RESERVED_CT_2";
4391 logtext = "REVERSE_CHARGING";
4394 logtext = "REMOTE_HOLD";
4397 logtext = "REMOTE_RETRIEVAL";
4400 logtext = "CALL_IS_DIVERTING";
4403 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
4407 trace_header("NOTIFY", dir);
4408 if (dir == DIRECTION_OUT)
4409 add_trace("to", NULL, "CH(%lu)", port_id);
4410 if (dir == DIRECTION_IN)
4411 add_trace("from", NULL, "CH(%lu)", port_id);
4412 if (param->notifyinfo.notify)
4413 add_trace("indicator", NULL, "%s", logtext);
4414 if (param->notifyinfo.id[0])
4416 add_trace("redir'on", "number", "%s", numberrize_callerinfo(param->notifyinfo.id, param->notifyinfo.ntype));
4417 switch(param->notifyinfo.present)
4419 case INFO_PRESENT_RESTRICTED:
4420 add_trace("redir'on", "present", "restricted");
4422 case INFO_PRESENT_ALLOWED:
4423 add_trace("redir'on", "present", "allowed");
4426 add_trace("redir'on", "present", "not available");
4429 if (param->notifyinfo.display[0])
4430 add_trace("display", NULL, "%s", param->notifyinfo.display);
4434 case MESSAGE_INFORMATION:
4435 trace_header("INFORMATION", dir);
4436 if (dir == DIRECTION_OUT)
4437 add_trace("to", NULL, "CH(%lu)", port_id);
4438 if (dir == DIRECTION_IN)
4439 add_trace("from", NULL, "CH(%lu)", port_id);
4440 add_trace("dialing", NULL, "%s", param->information.id);
4444 case MESSAGE_FACILITY:
4445 trace_header("FACILITY", dir);
4446 if (dir == DIRECTION_OUT)
4447 add_trace("to", NULL, "CH(%lu)", port_id);
4448 if (dir == DIRECTION_IN)
4449 add_trace("from", NULL, "CH(%lu)", port_id);
4454 trace_header("TONE", dir);
4455 if (dir == DIRECTION_OUT)
4456 add_trace("to", NULL, "CH(%lu)", port_id);
4457 if (dir == DIRECTION_IN)
4458 add_trace("from", NULL, "CH(%lu)", port_id);
4459 if (param->tone.name[0])
4461 add_trace("directory", NULL, "%s", param->tone.dir[0]?param->tone.dir:"default");
4462 add_trace("name", NULL, "%s", param->tone.name);
4464 add_trace("off", NULL, NULL);
4468 case MESSAGE_SUSPEND:
4469 case MESSAGE_RESUME:
4470 if (message_type == MESSAGE_SUSPEND)
4471 trace_header("SUSPEND", dir);
4473 trace_header("RESUME", dir);
4474 if (dir == DIRECTION_OUT)
4475 add_trace("to", NULL, "CH(%lu)", port_id);
4476 if (dir == DIRECTION_IN)
4477 add_trace("from", NULL, "CH(%lu)", port_id);
4478 if (param->parkinfo.len)
4479 add_trace("length", NULL, "%d", param->parkinfo.len);
4484 case MESSAGE_BCHANNEL:
4485 trace_header("BCHANNEL", dir);
4486 switch(param->bchannel.type)
4488 case BCHANNEL_REQUEST:
4489 add_trace("type", NULL, "request");
4491 case BCHANNEL_ASSIGN:
4492 add_trace("type", NULL, "assign");
4494 case BCHANNEL_ASSIGN_ACK:
4495 add_trace("type", NULL, "assign_ack");
4497 case BCHANNEL_REMOVE:
4498 add_trace("type", NULL, "remove");
4500 case BCHANNEL_REMOVE_ACK:
4501 add_trace("type", NULL, "remove_ack");
4504 if (param->bchannel.addr)
4505 add_trace("address", NULL, "%x", param->bchannel.addr);
4511 PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message_type);
4515 void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cause, int location, char *display)
4517 struct message *message;
4521 if (!portlist->port_id)
4524 if (!e_connectedmode)
4526 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT);
4527 message->param.disconnectinfo.cause = cause;
4528 message->param.disconnectinfo.location = location;
4530 SCPY(message->param.disconnectinfo.display, display);
4532 SCPY(message->param.disconnectinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4535 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
4537 SCPY(message->param.notifyinfo.display, display);
4539 SCPY(message->param.notifyinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4541 message_put(message);
4542 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);