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 */
701 if (e_join_pattern /* pattern are provided */
702 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_SETUP)
703 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_OVERLAP)
704 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_IN_PROCEEDING)
705 && !(e_ext.own_alerting && e_state == EPOINT_STATE_IN_ALERTING)
706 && !(e_ext.own_cause && e_state == EPOINT_STATE_IN_DISCONNECT)
707 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_SETUP)
708 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_OVERLAP)
709 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_OUT_PROCEEDING)
710 && !(e_ext.own_alerting && e_state == EPOINT_STATE_OUT_ALERTING)
711 && !(e_ext.own_cause && e_state == EPOINT_STATE_OUT_DISCONNECT)
712 && tone[0] && !!strncmp(tone,"crypt_*",6))
714 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) tone not provided since patterns are available\n", ea_endpoint->ep_serial);
720 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_TONE);
721 SCPY(message->param.tone.dir, e_ext.tones_dir[0]?e_ext.tones_dir:options.tones_dir);
722 SCPY(message->param.tone.name, tone);
723 message_put(message);
724 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
727 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port to notify tone.\n", ea_endpoint->ep_serial);
734 * hunts an mISDNport that is available for an outgoing call
735 * if no ifname was given, any interface that is not an extension
738 struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel)
740 struct interface *interface;
741 struct interface_port *ifport, *ifport_start;
742 struct select_channel *selchannel;
743 struct mISDNport *mISDNport;
746 interface = interface_first;
748 /* first find the given interface or, if not given, one with no extension */
753 /* check for given interface */
756 if (!strcasecmp(interface->name, ifname))
758 /* found explicit interface */
759 trace_header("CHANNEL SELECTION (found interface)", DIRECTION_NONE);
760 add_trace("interface", NULL, "%s", ifname);
767 if (!interface->extension)
769 /* found non extension */
770 trace_header("CHANNEL SELECTION (found non extension interface)", DIRECTION_NONE);
771 add_trace("interface", NULL, "%s", interface->name);
777 interface = interface->next;
781 /* see if interface has ports */
782 if (!interface->ifport)
785 trace_header("CHANNEL SELECTION (interface has no active ports, skipping)", DIRECTION_NONE);
786 add_trace("interface", NULL, "%s", interface->name);
788 interface = interface->next;
792 /* select port by algorithm */
793 ifport_start = interface->ifport;
795 if (interface->hunt == HUNT_ROUNDROBIN)
797 while(ifport_start->next && index<interface->hunt_next)
799 ifport_start = ifport_start->next;
802 trace_header("CHANNEL SELECTION (starting round-robin)", DIRECTION_NONE);
803 add_trace("port", NULL, "%d", ifport_start->portnum);
804 add_trace("position", NULL, "%d", index);
809 ifport = ifport_start;
812 /* see if port is available */
813 if (!ifport->mISDNport)
815 trace_header("CHANNEL SELECTION (port not available, skipping)", DIRECTION_NONE);
816 add_trace("port", NULL, "%d", ifport->portnum);
817 add_trace("position", NULL, "%d", index);
821 mISDNport = ifport->mISDNport;
823 /* see if port is administratively blocked */
826 trace_header("CHANNEL SELECTION (port blocked by admin, skipping)", DIRECTION_NONE);
827 add_trace("port", NULL, "%d", ifport->portnum);
828 add_trace("position", NULL, "%d", index);
833 /* see if link is up on PTP*/
834 if (mISDNport->ptp && !mISDNport->l2link)
836 trace_header("CHANNEL SELECTION (port is ptp with layer 2 down, skipping)", DIRECTION_NONE);
837 add_trace("port", NULL, "%d", ifport->portnum);
838 add_trace("position", NULL, "%d", index);
843 /* check for channel form selection list */
845 selchannel = ifport->out_channel;
848 switch(selchannel->channel)
850 case CHANNEL_FREE: /* free channel */
851 if (mISDNport->b_reserved >= mISDNport->b_num)
852 break; /* all channel in use or reserverd */
855 while(i < mISDNport->b_num)
857 if (mISDNport->b_port[i] == NULL)
859 *channel = i+1+(i>=15);
860 trace_header("CHANNEL SELECTION (selecting free channel)", DIRECTION_NONE);
861 add_trace("port", NULL, "%d", ifport->portnum);
862 add_trace("position", NULL, "%d", index);
863 add_trace("channel", NULL, "%d", *channel);
871 case CHANNEL_ANY: /* don't ask for channel */
872 if (mISDNport->b_reserved >= mISDNport->b_num)
874 break; /* all channel in use or reserverd */
876 trace_header("CHANNEL SELECTION (using 'any channel')", DIRECTION_NONE);
877 add_trace("port", NULL, "%d", ifport->portnum);
878 add_trace("position", NULL, "%d", index);
880 *channel = CHANNEL_ANY;
883 case CHANNEL_NO: /* call waiting */
884 trace_header("CHANNEL SELECTION (using 'no channel', call-waiting)", DIRECTION_NONE);
885 add_trace("port", NULL, "%d", ifport->portnum);
886 add_trace("position", NULL, "%d", index);
888 *channel = CHANNEL_NO;
892 if (selchannel->channel<1 || selchannel->channel==16)
893 break; /* invalid channels */
894 i = selchannel->channel-1-(selchannel->channel>=17);
895 if (i >= mISDNport->b_num)
896 break; /* channel not in port */
897 if (mISDNport->b_port[i] == NULL)
899 *channel = selchannel->channel;
900 trace_header("CHANNEL SELECTION (selecting given channel)", DIRECTION_NONE);
901 add_trace("port", NULL, "%d", ifport->portnum);
902 add_trace("position", NULL, "%d", index);
903 add_trace("channel", NULL, "%d", *channel);
910 break; /* found channel */
911 selchannel = selchannel->next;
914 /* if channel was found, return mISDNport and channel */
917 /* setting next port to start next time */
918 if (interface->hunt == HUNT_ROUNDROBIN)
923 interface->hunt_next = index;
929 trace_header("CHANNEL SELECTION (skipping, no channel found)", DIRECTION_NONE);
930 add_trace("port", NULL, "%d", ifport->portnum);
931 add_trace("position", NULL, "%d", index);
935 /* go next port, until all ports are checked */
937 ifport = ifport->next;
941 ifport = interface->ifport;
943 if (ifport != ifport_start)
946 return(NULL); /* no port found */
949 /* outgoing setup to port(s)
950 * ports will be created and a setup is sent if everything is ok. otherwhise
951 * the endpoint is destroyed.
953 void EndpointAppPBX::out_setup(void)
955 struct dialing_info dialinginfo;
957 // class pdss1 *pdss1;
958 struct port_list *portlist;
959 struct message *message;
961 int cause = CAUSE_RESSOURCEUNAVAIL;
964 struct mISDNport *mISDNport;
967 class EndpointAppPBX *atemp;
968 // char allowed_ports[256];
970 char ifname[sizeof(e_ext.interfaces)],
972 struct port_settings port_settings;
976 /* create settings for creating port */
977 memset(&port_settings, 0, sizeof(port_settings));
979 SCPY(port_settings.tones_dir, e_ext.tones_dir);
981 SCPY(port_settings.tones_dir, options.tones_dir);
982 port_settings.tout_setup = e_ext.tout_setup;
983 port_settings.tout_dialing = e_ext.tout_dialing;
984 port_settings.tout_proceeding = e_ext.tout_proceeding;
985 port_settings.tout_alerting = e_ext.tout_alerting;
986 port_settings.tout_disconnect = e_ext.tout_disconnect;
987 // port_settings.tout_hold = e_ext.tout_hold;
988 // port_settings.tout_park = e_ext.tout_park;
989 port_settings.no_seconds = e_ext.no_seconds;
991 /* 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 */
993 /* check what dialinginfo.itype we got */
994 switch(e_dialinginfo.itype)
996 /* *********************** call to extension or vbox */
997 case INFO_ITYPE_ISDN_EXTENSION:
998 /* check if we deny incoming calls when we use an extension */
999 if (e_ext.noknocking)
1001 atemp = apppbx_first;
1005 if (!strcmp(atemp->e_ext.number, e_ext.number))
1007 atemp = atemp->next;
1011 PERROR("EPOINT(%d) noknocking and currently a call\n", ea_endpoint->ep_serial);
1012 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYSPE_ join, port */
1013 return; /* must exit here */
1016 /* FALL THROUGH !!!! */
1017 case INFO_ITYPE_VBOX:
1018 /* get dialed extension's info */
1019 // SCPY(exten, e_dialinginfo.id);
1020 // if (strchr(exten, ','))
1021 // *strchr(exten, ',') = '\0';
1022 // if (!read_extension(&e_ext, exten))
1023 if (!read_extension(&e_ext, e_dialinginfo.id))
1025 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) extension %s not configured\n", ea_endpoint->ep_serial, e_dialinginfo.id);
1026 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1027 return; /* must exit here */
1030 if (e_dialinginfo.itype == INFO_ITYPE_VBOX)
1032 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing directly to VBOX\n", ea_endpoint->ep_serial);
1037 /* string from unconditional call forward (cfu) */
1041 /* present to forwarded party */
1042 if (e_ext.anon_ignore && e_callerinfo.id[0])
1044 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1046 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
1050 /* string from busy call forward (cfb) */
1054 class EndpointAppPBX *checkapp = apppbx_first;
1057 if (checkapp != this) /* any other endpoint except our own */
1059 if (!strcmp(checkapp->e_ext.number, e_ext.number))
1061 /* present to forwarded party */
1062 if (e_ext.anon_ignore && e_callerinfo.id[0])
1064 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1066 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
1070 checkapp = checkapp->next;
1074 /* string from no-response call forward (cfnr) */
1078 /* when cfnr is done, out_setup() will setup the call */
1081 /* present to forwarded party */
1082 if (e_ext.anon_ignore && e_callerinfo.id[0])
1084 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1088 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
1090 e_cfnr_release = now + e_ext.cfnr_delay;
1091 e_cfnr_call = now + e_ext.cfnr_delay + 1; /* call one second after release */
1092 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);
1096 /* call to all internal interfaces */
1097 p = e_ext.interfaces;
1098 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) generating multiple joins for extension %s to interfaces %s\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
1102 while(*p!=',' && *p!='\0')
1104 SCCAT(ifname, *p++);
1107 /* found interface */
1108 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
1109 /* hunt for mISDNport and create Port */
1110 mISDNport = hunt_port(ifname, &channel);
1113 trace_header("INTERFACE (not found or busy)", DIRECTION_NONE);
1114 add_trace("interface", NULL, "%s", ifname);
1118 /* creating INTERNAL port */
1119 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1120 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force);
1122 FATAL("No memory for DSS1 Port instance\n");
1123 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
1124 memset(&dialinginfo, 0, sizeof(dialinginfo));
1125 SCPY(dialinginfo.id, e_dialinginfo.id);
1126 dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
1127 dialinginfo.ntype = e_dialinginfo.ntype;
1128 /* create port_list relation */
1129 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
1132 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1134 goto check_anycall_intern;
1136 /* directory.list */
1137 if (e_callerinfo.id[0] && (e_ext.centrex || e_ext.display_name))
1139 dirname = parse_directory(e_callerinfo.id, e_callerinfo.ntype);
1141 SCPY(e_callerinfo.name, dirname);
1143 // dss1 = (class Pdss1 *)port;
1145 //printf("INTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1146 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1147 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1148 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1149 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1150 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1151 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1152 //terminal if (e_dialinginfo.id)
1153 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1154 /* handle restricted caller ids */
1155 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);
1156 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);
1157 /* display callerid if desired for extension */
1158 SCPY(message->param.setup.callerinfo.display, apply_callerid_display(message->param.setup.callerinfo.id, message->param.setup.callerinfo.itype, message->param.setup.callerinfo.ntype, message->param.setup.callerinfo.present, message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name));
1159 //printf("\n\ndisplay = %s\n\n\n",message->param.setup.callerinfo.display);
1160 /* use cnip, if enabld */
1162 message->param.setup.callerinfo.name[0] = '\0';
1163 /* screen clip if prefix is required */
1164 if (message->param.setup.callerinfo.id[0] && e_ext.clip_prefix[0])
1166 SCPY(message->param.setup.callerinfo.id, e_ext.clip_prefix);
1167 SCAT(message->param.setup.callerinfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype));
1168 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1170 /* use internal caller id */
1171 if (e_callerinfo.extension[0] && (message->param.setup.callerinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
1173 SCPY(message->param.setup.callerinfo.id, e_callerinfo.extension);
1174 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1176 message_put(message);
1177 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1181 /* string from parallel call forward (cfp) */
1185 if (e_ext.anon_ignore && e_callerinfo.id[0])
1187 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1191 vbox_only: /* entry point for answering machine only */
1192 cfu_only: /* entry point for cfu */
1193 cfb_only: /* entry point for cfb */
1194 cfnr_only: /* entry point for cfnr */
1195 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call extension %s for external destiantion(s) '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
1200 /* only if vbox should be dialed, and terminal is given */
1201 if (!strcmp(p, "vbox") && e_ext.number[0])
1203 /* go to the end of p */
1206 /* answering vbox call */
1207 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) answering machine\n", ea_endpoint->ep_serial);
1209 if (!(port = new VBoxPort(PORT_TYPE_VBOX_OUT, &port_settings)))
1210 FATAL("No memory for VBOX Port instance\n");
1211 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocated port %s\n", ea_endpoint->ep_serial, port->p_name);
1212 UCPY(cfp, e_ext.number); /* cfp or any other direct forward/vbox */
1216 while(*p!=',' && *p!='\0')
1221 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cfp external %s\n", ea_endpoint->ep_serial, cfp);
1222 /* hunt for mISDNport and create Port */
1223 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1226 /* creating EXTERNAL port*/
1227 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1228 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)))
1229 FATAL("No memory for DSS1 Port instance\n");
1230 earlyb = mISDNport->earlyb;
1234 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1235 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1241 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port found or created, which is idle.\n", ea_endpoint->ep_serial);
1242 goto check_anycall_intern;
1244 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found or created port %s\n", ea_endpoint->ep_serial, port->p_name);
1245 memset(&dialinginfo, 0, sizeof(dialinginfo));
1246 SCPY(dialinginfo.id, cfp);
1247 dialinginfo.itype = INFO_ITYPE_ISDN;
1248 dialinginfo.ntype = e_dialinginfo.ntype;
1249 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
1252 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1254 goto check_anycall_intern;
1256 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1257 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1258 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1259 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1260 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1261 /* if clip is hidden */
1262 if (e_ext.clip==CLIP_HIDE && port->p_type!=PORT_TYPE_VBOX_OUT)
1264 SCPY(message->param.setup.callerinfo.id, e_ext.callerid);
1265 SCPY(message->param.setup.callerinfo.extension, e_ext.number);
1266 message->param.setup.callerinfo.ntype = e_ext.callerid_type;
1267 message->param.setup.callerinfo.present = e_ext.callerid_present;
1269 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1270 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1271 //terminal if (e_dialinginfo.id)
1272 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1273 /* handle restricted caller ids */
1274 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);
1275 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);
1276 /* display callerid if desired for extension */
1277 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));
1278 message_put(message);
1279 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1283 check_anycall_intern:
1284 /* now we have all ports created */
1287 trace_header("INTERFACE (no extension's interface)", DIRECTION_NONE);
1289 if (!ea_endpoint->ep_join_id)
1291 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1292 return; /* must exit here */
1296 /* *********************** external call */
1298 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id);
1299 /* call to extenal interfaces */
1300 p = e_dialinginfo.id;
1304 while(*p!=',' && *p!='\0')
1305 SCCAT(number, *p++);
1309 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");
1310 /* hunt for mISDNport and create Port */
1311 /* hunt for mISDNport and create Port */
1312 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1315 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1316 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1318 goto check_anycall_extern;
1320 /* creating EXTERNAL port*/
1321 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1322 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)))
1323 FATAL("No memory for DSS1 Port instance\n");
1324 earlyb = mISDNport->earlyb;
1325 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
1326 memset(&dialinginfo, 0, sizeof(dialinginfo));
1327 SCPY(dialinginfo.id, number);
1328 dialinginfo.itype = INFO_ITYPE_ISDN;
1329 dialinginfo.ntype = e_dialinginfo.ntype;
1330 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
1333 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1335 goto check_anycall_extern;
1337 // dss1 = (class Pdss1 *)port;
1338 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1339 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1340 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1341 SCPY(message->param.setup.dialinginfo.id, number);
1342 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1343 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1344 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1345 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1346 //terminal if (e_dialinginfo.id)
1347 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1348 /* handle restricted caller ids */
1349 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);
1350 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);
1351 /* display callerid if desired for extension */
1352 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));
1353 message_put(message);
1354 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1358 check_anycall_extern:
1359 /* now we have all ports created */
1362 trace_header("INTERFACE (no free ports found)", DIRECTION_NONE);
1364 if (!ea_endpoint->ep_join_id)
1366 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1367 return; /* must exit here */
1375 /* handler for endpoint
1379 int EndpointAppPBX::handler(void)
1381 if (e_crypt_state!=CM_ST_NULL)
1386 /* process answering machine (play) handling */
1389 if (e_action->index == ACTION_VBOX_PLAY)
1392 /* process action timeout */
1393 if (e_action_timeout)
1394 if (now_d >= e_action_timeout)
1396 if (e_state!=EPOINT_STATE_CONNECT)
1399 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current action timed out.\n", ea_endpoint->ep_serial);
1400 e_multipoint_cause = 0;
1401 e_multipoint_location = 0;
1402 new_state(EPOINT_STATE_IN_OVERLAP);
1405 return(1); /* we must exit, because our endpoint might be gone */
1407 e_action_timeout = 0;
1410 /* process action timeout */
1411 if (e_match_timeout)
1412 if (now_d >= e_match_timeout)
1415 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we got a match timeout.\n", ea_endpoint->ep_serial);
1417 return(1); /* we must exit, because our endpoint might be gone */
1422 /* process redialing (epoint redials to port) */
1425 if (now_d >= e_redial)
1428 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial.\n", ea_endpoint->ep_serial);
1430 new_state(EPOINT_STATE_OUT_SETUP);
1431 /* call special setup routine */
1438 /* process powerdialing (epoint redials to epoint) */
1439 if (e_powerdialing > 0)
1441 if (now_d >= e_powerdialing)
1443 e_powerdialing = -1; /* leave power dialing on */
1444 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial of powerdial.\n", ea_endpoint->ep_serial);
1447 e_ruleset = ruleset_main;
1449 e_rule = e_ruleset->rule_first;
1451 new_state(EPOINT_STATE_IN_OVERLAP);
1457 /* process call forward no response */
1460 struct port_list *portlist;
1461 struct message *message;
1463 if (now >= e_cfnr_release)
1465 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-no-response time has expired, hanging up.\n", ea_endpoint->ep_serial);
1468 /* release all ports */
1469 while((portlist = ea_endpoint->ep_portlist))
1471 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1472 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
1473 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1474 message_put(message);
1475 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1476 ea_endpoint->free_portlist(portlist);
1479 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1480 message->param.audiopath = CHANNEL_STATE_HOLD;
1481 message_put(message);
1482 /* indicate no patterns */
1483 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1484 message_put(message);
1485 /* set setup state, since we have no response from the new join */
1486 new_state(EPOINT_STATE_OUT_SETUP);
1491 if (now >= e_cfnr_call)
1493 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-busy time has expired, calling the forwarded number: %s.\n", ea_endpoint->ep_serial, e_ext.cfnr);
1499 /* handle connection to user */
1500 if (e_state == EPOINT_STATE_IDLE)
1502 /* epoint is idle, check callback */
1504 if (now_d >= e_callback)
1506 e_callback = 0; /* done with callback */
1507 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting callback.\n", ea_endpoint->ep_serial);
1508 new_state(EPOINT_STATE_OUT_SETUP);
1514 /* check for password timeout */
1516 if (e_action->index==ACTION_PASSWORD || e_action->index==ACTION_PASSWORD_WRITE)
1518 struct port_list *portlist;
1520 if (now >= e_password_timeout)
1522 e_ruleset = ruleset_main;
1524 e_rule = e_ruleset->rule_first;
1526 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) password timeout %s\n", ea_endpoint->ep_serial, e_extdialing);
1527 trace_header("PASSWORD timeout", DIRECTION_NONE);
1529 e_connectedmode = 0;
1531 new_state(EPOINT_STATE_OUT_DISCONNECT);
1532 portlist = ea_endpoint->ep_portlist;
1535 message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
1536 set_tone(portlist, "cause_10");
1546 /* doing a hookflash */
1547 void EndpointAppPBX::hookflash(void)
1551 /* be sure that we are active */
1553 e_tx_state = NOTIFY_STATE_ACTIVE;
1555 trace_header("HOOKFLASH DTMF", DIRECTION_NONE);
1557 if (ea_endpoint->ep_use > 1)
1559 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot hooflash while child process is running.\n", ea_endpoint->ep_serial);
1562 /* dialtone after pressing the hash key */
1563 process_hangup(e_join_cause, e_join_location);
1564 e_multipoint_cause = 0;
1565 e_multipoint_location = 0;
1566 port = find_port_id(ea_endpoint->ep_portlist->port_id);
1569 port->set_echotest(0);
1571 if (ea_endpoint->ep_join_id)
1573 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1575 e_ruleset = ruleset_main;
1577 e_rule = e_ruleset->rule_first;
1579 new_state(EPOINT_STATE_IN_OVERLAP);
1580 e_connectedmode = 1;
1581 SCPY(e_dialinginfo.id, e_ext.prefix);
1582 e_extdialing = e_dialinginfo.id;
1584 if (e_dialinginfo.id[0])
1586 set_tone(ea_endpoint->ep_portlist, "dialing");
1590 set_tone(ea_endpoint->ep_portlist, "dialpbx");
1597 /* messages from port
1599 /* port MESSAGE_SETUP */
1600 void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, union parameter *param)
1602 struct message *message;
1604 int writeext; /* flags need to write extension after modification */
1606 struct interface *interface;
1608 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1610 portlist->port_type = param->setup.port_type;
1611 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
1612 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
1613 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
1614 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
1615 e_dtmf = param->setup.dtmf;
1616 /* screen incoming caller id */
1617 interface = interface_first;
1620 if (!strcmp(e_callerinfo.interface, interface->name))
1624 interface = interface->next;
1627 screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface);
1629 /* process extension */
1630 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1632 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is extension\n", ea_endpoint->ep_serial);
1633 /* port makes call from extension */
1634 SCPY(e_callerinfo.extension, e_callerinfo.id);
1635 SCPY(e_ext.number, e_callerinfo.extension);
1636 SCPY(e_extension_interface, e_callerinfo.interface);
1639 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is external or voip\n", ea_endpoint->ep_serial);
1642 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1644 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1646 /* get extension's info about caller */
1647 if (!read_extension(&e_ext, e_ext.number))
1649 /* extension doesn't exist */
1650 trace_header("EXTENSION (not created)", DIRECTION_IN);
1651 add_trace("extension", NULL, "%s", e_ext.number);
1653 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
1654 new_state(EPOINT_STATE_OUT_DISCONNECT);
1655 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
1656 e_ext.number[0] = '\0'; /* no terminal */
1661 /* put prefix (next) in front of e_dialinginfo.id */
1664 SPRINT(buffer, "%s%s", e_ext.next, e_dialinginfo.id);
1665 SCPY(e_dialinginfo.id, buffer);
1666 e_ext.next[0] = '\0';
1668 } else if (e_ext.prefix[0])
1670 SPRINT(buffer, "%s%s", e_ext.prefix, e_dialinginfo.id);
1671 SCPY(e_dialinginfo.id, buffer);
1674 /* screen caller id by extension's config */
1675 e_callerinfo.screen = INFO_SCREEN_NETWORK;
1677 SCPY(e_callerinfo.name, e_ext.name);
1678 /* use caller id (or if exist: id_next_call) for this call */
1679 if (e_ext.id_next_call_present >= 0)
1681 SCPY(e_callerinfo.id, e_ext.id_next_call);
1682 /* if we restrict the pesentation */
1683 if (e_ext.id_next_call_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1684 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1685 else e_callerinfo.present = e_ext.id_next_call_present;
1686 e_callerinfo.ntype = e_ext.id_next_call_type;
1687 e_ext.id_next_call_present = -1;
1691 SCPY(e_callerinfo.id, e_ext.callerid);
1692 /* if we restrict the pesentation */
1693 if (e_ext.callerid_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1694 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1695 else e_callerinfo.present = e_ext.callerid_present;
1696 e_callerinfo.ntype = e_ext.callerid_type;
1699 /* extension is written */
1701 write_extension(&e_ext, e_ext.number);
1703 /* set volume of rx and tx */
1704 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1705 if (e_ext.txvol!=256 || e_ext.rxvol!=256)
1707 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
1708 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
1709 message->param.mISDNsignal.rxvol = e_ext.txvol;
1710 message->param.mISDNsignal.txvol = e_ext.rxvol;
1711 message_put(message);
1714 /* start recording if enabled */
1715 if (e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO))
1717 /* check if we are a terminal */
1718 if (e_ext.number[0] == '\0')
1719 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
1722 port = find_port_id(portlist->port_id);
1724 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
1729 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from external port\n", ea_endpoint->ep_serial);
1730 /* no terminal identification */
1731 e_ext.number[0] = '\0';
1732 e_extension_interface[0] = '\0';
1733 memset(&e_ext, 0, sizeof(e_ext));
1734 e_ext.rights = 4; /* right to dial internat */
1738 e_ruleset = ruleset_main;
1740 e_rule = e_ruleset->rule_first;
1742 e_extdialing = e_dialinginfo.id;
1743 new_state(EPOINT_STATE_IN_SETUP);
1744 if (e_dialinginfo.id[0])
1746 set_tone(portlist, "dialing");
1749 if (e_ext.number[0])
1750 set_tone(portlist, "dialpbx");
1752 set_tone(portlist, "dialtone");
1755 if (e_state == EPOINT_STATE_IN_SETUP)
1757 /* request MORE info, if not already at higher state */
1758 new_state(EPOINT_STATE_IN_OVERLAP);
1759 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_OVERLAP);
1760 message_put(message);
1761 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1765 /* port MESSAGE_INFORMATION */
1766 void EndpointAppPBX::port_information(struct port_list *portlist, int message_type, union parameter *param)
1768 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1772 /* turn off dtmf detection, in case dtmf is sent with keypad information */
1775 trace_header("DTMF (disabling due to keypad)", DIRECTION_IN);
1780 /* if vbox_play is done, the information are just used as they come */
1782 if (e_action->index == ACTION_VBOX_PLAY)
1784 /* concat dialing string */
1785 SCAT(e_dialinginfo.id, param->information.id);
1790 /* keypad when disconnect but in connected mode */
1791 if (e_state==EPOINT_STATE_OUT_DISCONNECT && e_connectedmode)
1793 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received after disconnect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1794 /* processing keypad function */
1795 if (param->information.id[0] == '0')
1802 /* keypad when connected */
1803 if (e_state == EPOINT_STATE_CONNECT)
1807 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1808 /* processing keypad function */
1809 if (param->information.id[0] == '0')
1813 if (param->information.id[0])
1814 keypad_function(param->information.id[0]);
1817 trace_header("DTMF (not enabled by extension's settings)", DIRECTION_IN);
1822 if (e_state != EPOINT_STATE_IN_OVERLAP)
1824 trace_header("DTMF (ignored, not connected and not dialing)", DIRECTION_IN);
1828 if (!param->information.id[0])
1830 if (e_dialinginfo.id[0]=='\0' && !e_action)
1832 set_tone(portlist, "dialing");
1835 if (e_action->index==ACTION_OUTDIAL
1836 || e_action->index==ACTION_EXTERNAL)
1839 set_tone(portlist, "dialing");
1840 else if (!e_extdialing[0])
1841 set_tone(portlist, "dialing");
1843 /* concat dialing string */
1844 SCAT(e_dialinginfo.id, param->information.id);
1848 /* port MESSAGE_DTMF */
1849 void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
1851 /* only if dtmf detection is enabled */
1854 trace_header("DTMF (disabled)", DIRECTION_IN);
1858 trace_header("DTMF", DIRECTION_IN);
1859 add_trace("digit", NULL, "%c", param->dtmf);
1863 NOTE: vbox is now handled due to overlap state
1864 /* if vbox_play is done, the dtmf digits are just used as they come */
1866 if (e_action->index == ACTION_VBOX_PLAY)
1868 /* concat dialing string */
1869 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id))
1871 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1872 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1875 /* continue to process *X# sequences */
1879 /* check for *X# sequence */
1880 if (e_state == EPOINT_STATE_CONNECT)
1882 if (e_dtmf_time+3 < now)
1884 /* the last digit was too far in the past to be a sequence */
1885 if (param->dtmf == '*')
1886 /* only start is allowed in the sequence */
1892 /* we have a sequence of digits, see what we got */
1893 if (param->dtmf == '*')
1895 else if (param->dtmf>='0' && param->dtmf<='9')
1897 /* we need to have a star before we receive the digit of the sequence */
1898 if (e_dtmf_last == '*')
1899 e_dtmf_last = param->dtmf;
1900 } else if (param->dtmf == '#')
1903 if (e_dtmf_last>='0' && e_dtmf_last<='9')
1905 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf sequence *%c# detected.\n", ea_endpoint->ep_serial, e_dtmf_last);
1906 if (e_dtmf_last == '0')
1911 /* processing keypad function */
1913 keypad_function(e_dtmf_last);
1919 /* set last time of dtmf */
1924 /* check for ## hookflash during dialing */
1926 if (e_action->index==ACTION_PASSWORD
1927 || e_action->index==ACTION_PASSWORD_WRITE)
1929 if (param->dtmf=='#') /* current digit is '#' */
1931 if (e_state==EPOINT_STATE_IN_DISCONNECT
1932 || (e_state!=EPOINT_STATE_CONNECT && e_dtmf_time+3>=now && e_dtmf_last=='#')) /* when disconnected, just #. when dialing, ##. */
1949 /* dialing using dtmf digit */
1950 if (e_state==EPOINT_STATE_IN_OVERLAP)// && e_state==e_connectedmode)
1952 if (e_dialinginfo.id[0]=='\0' && !e_action)
1954 set_tone(portlist, "dialing");
1956 /* concat dialing string */
1957 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id))
1959 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1960 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1966 /* port MESSAGE_CRYPT */
1967 void EndpointAppPBX::port_crypt(struct port_list *portlist, int message_type, union parameter *param)
1969 /* send crypt response to cryptman */
1970 if (param->crypt.type == CR_MESSAGE_IND)
1971 cryptman_msg2man(param->crypt.data, param->crypt.len);
1973 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
1976 /* port MESSAGE_OVERLAP */
1977 void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, union parameter *param)
1979 struct message *message;
1981 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1983 /* signal to call tool */
1984 admin_call_response(e_adminid, ADMIN_CALL_SETUP_ACK, "", 0, 0, 0);
1986 if (e_dialing_queue[0] && portlist)
1988 /* send what we have not dialed yet, because we had no setup complete */
1989 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing pending digits: '%s'\n", ea_endpoint->ep_serial, e_dialing_queue);
1990 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
1991 SCPY(message->param.information.id, e_dialing_queue);
1992 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
1993 message_put(message);
1994 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
1995 e_dialing_queue[0] = '\0';
1997 /* check if pattern is available */
1998 if (!ea_endpoint->ep_portlist->next && portlist->early_b) /* one port_list relation and tones available */
2000 /* indicate patterns */
2001 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2002 message_put(message);
2004 /* connect audio, if not already */
2005 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2006 message->param.audiopath = CHANNEL_STATE_CONNECT;
2007 message_put(message);
2010 /* indicate no patterns */
2011 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
2012 message_put(message);
2014 /* disconnect audio, if not already */
2015 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2016 message->param.audiopath = CHANNEL_STATE_HOLD;
2017 message_put(message);
2019 new_state(EPOINT_STATE_OUT_OVERLAP);
2020 /* if we are in a join */
2021 if (ea_endpoint->ep_join_id)
2023 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2024 memcpy(&message->param, param, sizeof(union parameter));
2025 message_put(message);
2029 /* port MESSAGE_PROCEEDING */
2030 void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_type, union parameter *param)
2032 struct message *message;
2034 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2036 /* signal to call tool */
2037 admin_call_response(e_adminid, ADMIN_CALL_PROCEEDING, "", 0, 0, 0);
2039 e_state = EPOINT_STATE_OUT_PROCEEDING;
2040 /* check if pattern is availatle */
2041 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
2043 /* indicate patterns */
2044 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2045 message_put(message);
2047 /* connect audio, if not already */
2048 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2049 message->param.audiopath = CHANNEL_STATE_CONNECT;
2050 message_put(message);
2053 /* indicate no patterns */
2054 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
2055 message_put(message);
2057 /* disconnect audio, if not already */
2058 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2059 message->param.audiopath = CHANNEL_STATE_HOLD;
2060 message_put(message);
2062 /* if we are in a call */
2063 if (ea_endpoint->ep_join_id)
2065 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2066 memcpy(&message->param, param, sizeof(union parameter));
2067 message_put(message);
2071 /* port MESSAGE_ALERTING */
2072 void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type, union parameter *param)
2074 struct message *message;
2076 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2078 /* signal to call tool */
2079 admin_call_response(e_adminid, ADMIN_CALL_ALERTING, "", 0, 0, 0);
2081 new_state(EPOINT_STATE_OUT_ALERTING);
2082 /* check if pattern is available */
2083 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
2085 /* indicate patterns */
2086 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2087 message_put(message);
2089 /* connect audio, if not already */
2090 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2091 message->param.audiopath = CHANNEL_STATE_CONNECT;
2092 message_put(message);
2095 /* indicate no patterns */
2096 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
2097 message_put(message);
2099 /* disconnect audio, if not already */
2100 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2101 message->param.audiopath = CHANNEL_STATE_HOLD;
2102 message_put(message);
2104 /* if we are in a call */
2105 if (ea_endpoint->ep_join_id)
2107 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2108 memcpy(&message->param, param, sizeof(union parameter));
2109 message_put(message);
2113 /* port MESSAGE_CONNECT */
2114 void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, union parameter *param)
2116 struct message *message;
2118 unsigned long port_id = portlist->port_id;
2119 struct port_list *tportlist;
2121 struct interface *interface;
2123 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2125 /* signal to call tool */
2126 admin_call_response(e_adminid, ADMIN_CALL_CONNECT, numberrize_callerinfo(param->connectinfo.id,param->connectinfo.ntype), 0, 0, 0);
2128 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_connectinfo));
2129 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (start)\n", ea_endpoint->ep_serial);
2130 while(ea_endpoint->ep_portlist->next) /* as long as we have at least two ports */
2132 tportlist = ea_endpoint->ep_portlist;
2133 if (tportlist->port_id == port_id) /* if the first portlist is the calling one, the second must be a different one */
2134 tportlist = tportlist->next;
2135 if (tportlist->port_id == port_id)
2136 FATAL("EPOINT(%d) this should not happen since the portlist list must not have two links to the same port - exitting.\n");
2137 message = message_create(ea_endpoint->ep_serial, tportlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2138 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
2139 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2140 message_put(message);
2141 logmessage(message->type, &message->param, tportlist->port_id, DIRECTION_OUT);
2142 ea_endpoint->free_portlist(tportlist);
2144 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (end)\n", ea_endpoint->ep_serial);
2148 /* screen incoming connected id */
2149 interface = interface_first;
2152 if (!strcmp(e_connectinfo.interface, interface->name))
2156 interface = interface->next;
2159 screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface);
2161 /* screen connected name */
2163 SCPY(e_connectinfo.name, e_ext.name);
2165 /* add internal id to colp */
2166 SCPY(e_connectinfo.extension, e_ext.number);
2168 /* we store the connected port number */
2169 SCPY(e_extension_interface, e_connectinfo.interface);
2171 /* for internal and am calls, we get the extension's id */
2172 if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE)
2174 SCPY(e_connectinfo.id, e_ext.callerid);
2175 SCPY(e_connectinfo.extension, e_ext.number);
2176 e_connectinfo.itype = INFO_ITYPE_ISDN_EXTENSION;
2177 e_connectinfo.ntype = e_ext.callerid_type;
2178 e_connectinfo.present = e_ext.callerid_present;
2180 if (portlist->port_type==PORT_TYPE_VBOX_OUT)
2182 e_connectinfo.itype = INFO_ITYPE_VBOX;
2183 e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2186 new_state(EPOINT_STATE_CONNECT);
2188 /* set volume of rx and tx */
2189 if (e_ext.txvol!=256 || e_ext.rxvol!=256)
2191 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2192 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2193 message->param.mISDNsignal.rxvol = e_ext.txvol;
2194 message->param.mISDNsignal.txvol = e_ext.rxvol;
2195 message_put(message);
2198 e_cfnr_call = e_cfnr_release = 0;
2199 if (e_ext.number[0])
2200 e_dtmf = 1; /* allow dtmf */
2203 /* other calls with no caller id (or not available for the extension) and force colp */
2204 if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE)
2206 e_connectinfo.present = INFO_PRESENT_NOTAVAIL;
2207 if (portlist->port_type==PORT_TYPE_DSS1_TE_OUT || portlist->port_type==PORT_TYPE_DSS1_NT_OUT) /* external extension answered */
2209 port = find_port_id(portlist->port_id);
2212 SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.id, &e_connectinfo.ntype));
2213 e_connectinfo.present = INFO_PRESENT_ALLOWED;
2218 /* send connect to join */
2219 if (ea_endpoint->ep_join_id)
2221 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2222 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
2223 message_put(message);
2225 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2226 message->param.audiopath = CHANNEL_STATE_CONNECT;
2227 message_put(message);
2228 } else if (!e_adminid)
2231 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have a callback, so we create a call with cbcaller: \"%s\".\n", ea_endpoint->ep_serial, e_cbcaller);
2232 SCPY(e_ext.number, e_cbcaller);
2233 new_state(EPOINT_STATE_IN_OVERLAP);
2234 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) callback from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2236 /* get extension's info about terminal */
2237 if (!read_extension(&e_ext, e_ext.number))
2239 /* extension doesn't exist */
2240 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2241 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
2242 new_state(EPOINT_STATE_OUT_DISCONNECT);
2243 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
2247 /* put prefix in front of e_cbdialing */
2248 SPRINT(buffer, "%s%s", e_ext.prefix, e_cbdialing);
2249 SCPY(e_dialinginfo.id, buffer);
2250 e_dialinginfo.itype = INFO_ITYPE_ISDN;
2251 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
2253 /* use caller id (or if exist: id_next_call) for this call */
2254 e_callerinfo.screen = INFO_SCREEN_NETWORK;
2255 SCPY(e_callerinfo.extension, e_ext.number);
2256 if (e_ext.id_next_call_present >= 0)
2258 SCPY(e_callerinfo.id, e_ext.id_next_call);
2259 e_callerinfo.present = e_ext.id_next_call_present;
2260 e_callerinfo.ntype = e_ext.id_next_call_type;
2261 e_ext.id_next_call_present = -1;
2262 /* extension is written */
2263 write_extension(&e_ext, e_ext.number);
2266 SCPY(e_callerinfo.id, e_ext.callerid);
2267 e_callerinfo.present = e_ext.callerid_present;
2268 e_callerinfo.ntype = e_ext.callerid_type;
2271 e_connectedmode = 1; /* dtmf-hangup & disconnect prevention */
2274 /* check if caller id is NOT authenticated */
2275 if (!parse_callbackauth(e_ext.number, &e_callbackinfo))
2277 /* make call state to enter password */
2278 new_state(EPOINT_STATE_IN_OVERLAP);
2279 e_action = &action_password_write;
2280 e_match_timeout = 0;
2281 e_match_to_action = NULL;
2282 e_dialinginfo.id[0] = '\0';
2283 e_extdialing = strchr(e_dialinginfo.id, '\0');
2284 e_password_timeout = now+20;
2288 /* incoming call (callback) */
2289 e_ruleset = ruleset_main;
2291 e_rule = e_ruleset->rule_first;
2293 e_extdialing = e_dialinginfo.id;
2294 if (e_dialinginfo.id[0])
2296 set_tone(portlist, "dialing");
2300 set_tone(portlist, "dialpbx");
2303 } else /* testcall */
2305 set_tone(portlist, "hold");
2308 /* start recording if enabled, not when answering machine answers */
2309 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))
2311 /* check if we are a terminal */
2312 if (e_ext.number[0] == '\0')
2313 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
2316 port = find_port_id(portlist->port_id);
2318 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
2323 /* port MESSAGE_DISCONNECT MESSAGE_RELEASE */
2324 void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
2326 struct message *message;
2328 unsigned long port_id = portlist->port_id;
2332 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2334 /* signal to call tool */
2335 admin_call_response(e_adminid, (message_type==MESSAGE_DISCONNECT)?ADMIN_CALL_DISCONNECT:ADMIN_CALL_RELEASE, "", param->disconnectinfo.cause, param->disconnectinfo.location, 0);
2337 //#warning does this work? only disconnect when incoming port hat not already disconnected yet?
2338 if (e_state==EPOINT_STATE_IN_DISCONNECT && message_type!=MESSAGE_RELEASE)// || e_state==EPOINT_STATE_OUT_DISCONNECT || e_state==EPOINT_STATE_IDLE)
2340 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are already disconnected.\n", ea_endpoint->ep_serial);
2345 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);
2346 collect_cause(&e_multipoint_cause, &e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location);
2347 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new multipoint cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location);
2349 /* check if we have more than one portlist relation and we just ignore the disconnect */
2350 if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist->next)
2352 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the disconnect was from a multipoint call. we just release that relation.\n", ea_endpoint->ep_serial);
2353 portlist = ea_endpoint->ep_portlist;
2356 if (portlist->port_id == port_id)
2358 portlist = portlist->next;
2361 FATAL("EPOINT(%d) no portlist related to the calling port.\n", ea_endpoint->ep_serial);
2362 if (message_type != MESSAGE_RELEASE)
2364 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2365 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2366 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2367 message_put(message);
2368 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2370 ea_endpoint->free_portlist(portlist);
2371 return; /* one relation removed */
2373 if (e_state == EPOINT_STATE_CONNECT)
2375 /* use cause from port after connect */
2376 cause = param->disconnectinfo.cause;
2377 location = param->disconnectinfo.location;
2380 /* use multipoint cause if no connect yet */
2381 if (e_multipoint_cause)
2383 cause = e_multipoint_cause;
2384 location = e_multipoint_location;
2387 cause = CAUSE_NOUSER;
2388 location = LOCATION_PRIVATE_LOCAL;
2392 e_cfnr_call = e_cfnr_release = 0;
2394 /* process hangup */
2395 process_hangup(e_join_cause, e_join_location);
2396 e_multipoint_cause = 0;
2397 e_multipoint_location = 0;
2399 if (message_type == MESSAGE_DISCONNECT)
2401 /* tone to disconnected end */
2402 SPRINT(buffer, "cause_%02x", cause);
2403 if (ea_endpoint->ep_portlist)
2404 set_tone(ea_endpoint->ep_portlist, buffer);
2406 new_state(EPOINT_STATE_IN_DISCONNECT);
2409 if (ea_endpoint->ep_join_id)
2411 int haspatterns = 0;
2412 /* check if pattern is available */
2413 if (ea_endpoint->ep_portlist)
2414 if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->early_b)
2415 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
2416 && message_type != MESSAGE_RELEASE) // if we release, we are done
2420 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has patterns.\n", ea_endpoint->ep_serial);
2421 /* indicate patterns */
2422 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2423 message_put(message);
2424 /* connect audio, if not already */
2425 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2426 message->param.audiopath = CHANNEL_STATE_CONNECT;
2427 message_put(message);
2428 /* send disconnect */
2429 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2430 memcpy(&message->param, param, sizeof(union parameter));
2431 message_put(message);
2432 /* disable encryption if disconnected */
2433 //PERROR("REMOVE ME: state =%d, %d\n", e_crypt_state, e_crypt);
2435 cryptman_message(CI_DISCONNECT_IND, NULL, 0);
2439 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
2442 if (message_type == MESSAGE_RELEASE)
2443 ea_endpoint->free_portlist(portlist);
2444 release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, callcause, portcause */
2445 return; /* must exit here */
2448 /* port MESSAGE_TIMEOUT */
2449 void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type, union parameter *param)
2453 trace_header("TIMEOUT", DIRECTION_IN);
2454 message_type = MESSAGE_DISCONNECT;
2455 switch (param->state)
2457 case PORT_STATE_OUT_SETUP:
2458 case PORT_STATE_OUT_OVERLAP:
2459 add_trace("state", NULL, "outgoing setup/dialing");
2461 /* no user responding */
2462 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2463 return; /* must exit here */
2465 case PORT_STATE_IN_SETUP:
2466 case PORT_STATE_IN_OVERLAP:
2467 add_trace("state", NULL, "incoming setup/dialing");
2468 param->disconnectinfo.cause = CAUSE_INVALID; /* number incomplete */
2469 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2472 case PORT_STATE_OUT_PROCEEDING:
2473 add_trace("state", NULL, "outgoing proceeding");
2475 param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
2476 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2477 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2478 return; /* must exit here */
2480 case PORT_STATE_IN_PROCEEDING:
2481 add_trace("state", NULL, "incoming proceeding");
2482 param->disconnectinfo.cause = CAUSE_NOUSER;
2483 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL; /* no user responding */
2486 case PORT_STATE_OUT_ALERTING:
2487 add_trace("state", NULL, "outgoing alerting");
2489 param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
2490 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2491 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2492 return; /* must exit here */
2494 case PORT_STATE_CONNECT:
2495 add_trace("state", NULL, "connect");
2497 param->disconnectinfo.cause = CAUSE_NORMAL; /* normal */
2498 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2499 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2500 return; /* must exit here */
2502 case PORT_STATE_IN_ALERTING:
2503 add_trace("state", NULL, "incoming alerting");
2504 param->disconnectinfo.cause = CAUSE_NOANSWER;
2505 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2508 case PORT_STATE_IN_DISCONNECT:
2509 case PORT_STATE_OUT_DISCONNECT:
2510 add_trace("state", NULL, "disconnect");
2512 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
2513 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2514 return; /* must exit here */
2517 param->disconnectinfo.cause = 31; /* normal unspecified */
2518 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2521 /* release call, disconnect isdn */
2523 new_state(EPOINT_STATE_OUT_DISCONNECT);
2524 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2525 SCPY(e_tone, cause);
2528 set_tone(portlist, cause);
2529 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2530 portlist = portlist->next;
2532 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
2535 /* port MESSAGE_NOTIFY */
2536 void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, union parameter *param)
2538 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2540 struct message *message;
2544 /* signal to call tool */
2545 admin_call_response(e_adminid, ADMIN_CALL_NOTIFY, numberrize_callerinfo(param->notifyinfo.id,param->notifyinfo.ntype), 0, 0, param->notifyinfo.notify);
2546 if (param->notifyinfo.notify)
2548 e_rx_state = track_notify(e_rx_state, param->notifyinfo.notify);
2551 /* if we get notification from stack, local shows if we disabled/enabled audio stream */
2552 if (param->notifyinfo.local) switch(param->notifyinfo.notify)
2554 case INFO_NOTIFY_REMOTE_HOLD:
2555 case INFO_NOTIFY_USER_SUSPENDED:
2556 /* tell call about it */
2557 if (ea_endpoint->ep_join_id)
2559 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2560 message->param.audiopath = CHANNEL_STATE_HOLD;
2561 message_put(message);
2565 case INFO_NOTIFY_REMOTE_RETRIEVAL:
2566 case INFO_NOTIFY_USER_RESUMED:
2567 /* set volume of rx and tx */
2568 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
2569 if (e_ext.txvol!=256 || e_ext.rxvol!=256)
2572 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2573 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2574 message->param.mISDNsignal.rxvol = e_ext.txvol;
2575 message->param.mISDNsignal.txvol = e_ext.rxvol;
2576 message_put(message);
2578 /* set current tone */
2580 set_tone(portlist, e_tone);
2581 /* tell call about it */
2582 if (ea_endpoint->ep_join_id)
2584 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2585 message->param.audiopath = CHANNEL_STATE_CONNECT;
2586 message_put(message);
2591 /* get name of notify */
2592 switch(param->notifyinfo.notify)
2598 logtext = "USER_SUSPENDED";
2601 logtext = "BEARER_SERVICE_CHANGED";
2604 logtext = "USER_RESUMED";
2607 logtext = "CONFERENCE_ESTABLISHED";
2610 logtext = "CONFERENCE_DISCONNECTED";
2613 logtext = "OTHER_PARTY_ADDED";
2616 logtext = "ISOLATED";
2619 logtext = "REATTACHED";
2622 logtext = "OTHER_PARTY_ISOLATED";
2625 logtext = "OTHER_PARTY_REATTACHED";
2628 logtext = "OTHER_PARTY_SPLIT";
2631 logtext = "OTHER_PARTY_DISCONNECTED";
2634 logtext = "CONFERENCE_FLOATING";
2637 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
2640 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
2643 logtext = "CALL_IS_A_WAITING_CALL";
2646 logtext = "DIVERSION_ACTIVATED";
2649 logtext = "RESERVED_CT_1";
2652 logtext = "RESERVED_CT_2";
2655 logtext = "REVERSE_CHARGING";
2658 logtext = "REMOTE_HOLD";
2661 logtext = "REMOTE_RETRIEVAL";
2664 logtext = "CALL_IS_DIVERTING";
2667 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
2672 /* notify call if available */
2673 if (ea_endpoint->ep_join_id)
2675 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOTIFY);
2676 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
2677 message_put(message);
2682 /* port MESSAGE_FACILITY */
2683 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
2685 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2687 struct message *message;
2689 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_FACILITY);
2690 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2691 message_put(message);
2694 /* port MESSAGE_SUSPEND */
2695 /* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
2696 void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
2698 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2700 /* epoint is now parked */
2701 ea_endpoint->ep_park = 1;
2702 memcpy(ea_endpoint->ep_park_callid, param->parkinfo.callid, sizeof(ea_endpoint->ep_park_callid));
2703 ea_endpoint->ep_park_len = (param->parkinfo.len>8)?8:param->parkinfo.len;
2705 /* remove port relation */
2706 ea_endpoint->free_portlist(portlist);
2709 /* port MESSAGE_RESUME */
2710 /* NOTE: before resume, the active-notification must be done in order to set call mixer */
2711 void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
2713 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2715 /* epoint is now resumed */
2716 ea_endpoint->ep_park = 0;
2721 /* port sends message to the endpoint
2723 void EndpointAppPBX::ea_message_port(unsigned long port_id, int message_type, union parameter *param)
2725 struct port_list *portlist;
2726 struct message *message;
2728 portlist = ea_endpoint->ep_portlist;
2731 if (port_id == portlist->port_id)
2733 portlist = portlist->next;
2737 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);
2741 // PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
2742 switch(message_type)
2744 case MESSAGE_DATA: /* data from port */
2745 /* check if there is a call */
2746 if (!ea_endpoint->ep_join_id)
2748 /* continue if only one portlist */
2749 if (ea_endpoint->ep_portlist->next != NULL)
2751 /* forward message */
2752 message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2755 case MESSAGE_TONE_EOF: /* tone is end of file */
2756 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
2759 if (e_action->index == ACTION_VBOX_PLAY)
2763 if (e_action->index == ACTION_EFI)
2770 case MESSAGE_TONE_COUNTER: /* counter info received */
2771 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);
2773 if (e_action->index == ACTION_VBOX_PLAY)
2775 e_vbox_counter = param->counter.current;
2776 if (param->counter.max >= 0)
2777 e_vbox_counter_max = param->counter.max;
2781 /* PORT sends SETUP message */
2783 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);
2784 if (e_state!=EPOINT_STATE_IDLE)
2786 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
2789 port_setup(portlist, message_type, param);
2792 /* PORT sends INFORMATION message */
2793 case MESSAGE_INFORMATION: /* additional digits received */
2794 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);
2795 port_information(portlist, message_type, param);
2798 /* PORT sends FACILITY message */
2799 case MESSAGE_FACILITY:
2800 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2801 port_facility(portlist, message_type, param);
2804 /* PORT sends DTMF message */
2805 case MESSAGE_DTMF: /* dtmf digits received */
2806 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);
2807 port_dtmf(portlist, message_type, param);
2810 /* PORT sends CRYPT message */
2811 case MESSAGE_CRYPT: /* crypt response received */
2812 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) crypt response=%d\n", ea_endpoint->ep_serial, param->crypt.type);
2813 port_crypt(portlist, message_type, param);
2816 /* PORT sends MORE message */
2817 case MESSAGE_OVERLAP:
2818 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);
2819 if (e_state != EPOINT_STATE_OUT_SETUP)
2821 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);
2824 port_overlap(portlist, message_type, param);
2827 /* PORT sends PROCEEDING message */
2828 case MESSAGE_PROCEEDING: /* port is proceeding */
2829 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);
2830 if (e_state!=EPOINT_STATE_OUT_SETUP
2831 && e_state!=EPOINT_STATE_OUT_OVERLAP)
2833 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);
2836 port_proceeding(portlist, message_type, param);
2839 /* PORT sends ALERTING message */
2840 case MESSAGE_ALERTING:
2841 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);
2842 if (e_state!=EPOINT_STATE_OUT_SETUP
2843 && e_state!=EPOINT_STATE_OUT_OVERLAP
2844 && e_state!=EPOINT_STATE_OUT_PROCEEDING)
2846 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);
2849 port_alerting(portlist, message_type, param);
2852 /* PORT sends CONNECT message */
2853 case MESSAGE_CONNECT:
2854 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);
2855 if (e_state!=EPOINT_STATE_OUT_SETUP
2856 && e_state!=EPOINT_STATE_OUT_OVERLAP
2857 && e_state!=EPOINT_STATE_OUT_PROCEEDING
2858 && e_state!=EPOINT_STATE_OUT_ALERTING)
2860 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
2863 port_connect(portlist, message_type, param);
2866 /* PORT sends DISCONNECT message */
2867 case MESSAGE_DISCONNECT: /* port is disconnected */
2868 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);
2869 port_disconnect_release(portlist, message_type, param);
2872 /* PORT sends a RELEASE message */
2873 case MESSAGE_RELEASE: /* port releases */
2874 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);
2875 /* portlist is release at port_disconnect_release, thanx Paul */
2876 port_disconnect_release(portlist, message_type, param);
2879 /* PORT sends a TIMEOUT message */
2880 case MESSAGE_TIMEOUT:
2881 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);
2882 port_timeout(portlist, message_type, param);
2883 break; /* release */
2885 /* PORT sends a NOTIFY message */
2886 case MESSAGE_NOTIFY:
2887 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);
2888 port_notify(portlist, message_type, param);
2891 /* PORT sends a SUSPEND message */
2892 case MESSAGE_SUSPEND:
2893 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);
2894 port_suspend(portlist, message_type, param);
2895 break; /* suspend */
2897 /* PORT sends a RESUME message */
2898 case MESSAGE_RESUME:
2899 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);
2900 port_resume(portlist, message_type, param);
2904 /* port assigns bchannel */
2905 case MESSAGE_BCHANNEL: /* bchannel assignment messafe */
2906 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);
2907 /* only one port is expected to be connected to bchannel */
2908 message = message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2909 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_IN);
2915 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);
2918 /* Note: this endpoint may be destroyed, so we MUST return */
2922 /* messages from join
2924 /* join MESSAGE_CRYPT */
2925 void EndpointAppPBX::join_crypt(struct port_list *portlist, int message_type, union parameter *param)
2927 switch(param->crypt.type)
2929 /* message from remote port to "crypt manager" */
2930 case CU_ACTK_REQ: /* activate key-exchange */
2931 case CU_ACTS_REQ: /* activate shared key */
2932 case CU_DACT_REQ: /* deactivate */
2933 case CU_INFO_REQ: /* request last info message */
2934 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2937 /* message from "crypt manager" to user */
2938 case CU_ACTK_CONF: /* key-echange done */
2939 case CU_ACTS_CONF: /* shared key done */
2940 case CU_DACT_CONF: /* deactivated */
2941 case CU_DACT_IND: /* deactivated */
2942 case CU_ERROR_IND: /* receive error message */
2943 case CU_INFO_IND: /* receive info message */
2944 case CU_INFO_CONF: /* receive info message */
2945 encrypt_result(param->crypt.type, (char *)param->crypt.data);
2949 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);
2953 /* join MESSAGE_INFORMATION */
2954 void EndpointAppPBX::join_information(struct port_list *portlist, int message_type, union parameter *param)
2956 struct message *message;
2962 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2963 memcpy(&message->param.information, ¶m->information, sizeof(struct dialing_info));
2964 message_put(message);
2965 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2966 portlist = portlist->next;
2970 /* join MESSAGE_FACILITY */
2971 void EndpointAppPBX::join_facility(struct port_list *portlist, int message_type, union parameter *param)
2973 struct message *message;
2975 if (!e_ext.facility)
2982 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_FACILITY);
2983 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2984 message_put(message);
2985 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2986 portlist = portlist->next;
2990 /* join MESSAGE_MORE */
2991 void EndpointAppPBX::join_overlap(struct port_list *portlist, int message_type, union parameter *param)
2993 struct message *message;
2995 new_state(EPOINT_STATE_IN_OVERLAP);
2998 if (e_join_pattern && e_ext.own_setup)
3000 /* disconnect audio */
3001 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3002 message->param.audiopath = CHANNEL_STATE_HOLD;
3003 message_put(message);
3005 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
3007 set_tone(portlist, "dialtone");
3010 if (e_ext.number[0])
3011 set_tone(portlist, "dialpbx");
3013 set_tone(portlist, "dialtone");
3016 /* join MESSAGE_PROCEEDING */
3017 void EndpointAppPBX::join_proceeding(struct port_list *portlist, int message_type, union parameter *param)
3019 struct message *message;
3021 new_state(EPOINT_STATE_IN_PROCEEDING);
3023 /* own proceeding tone */
3026 /* connect / disconnect audio */
3027 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3028 if (e_ext.own_proceeding)
3029 message->param.audiopath = CHANNEL_STATE_HOLD;
3031 message->param.audiopath = CHANNEL_STATE_CONNECT;
3032 message_put(message);
3034 // UCPY(e_join_tone, "proceeding");
3037 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3038 message_put(message);
3039 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3041 set_tone(portlist, "proceeding");
3044 /* join MESSAGE_ALERTING */
3045 void EndpointAppPBX::join_alerting(struct port_list *portlist, int message_type, union parameter *param)
3047 struct message *message;
3049 new_state(EPOINT_STATE_IN_ALERTING);
3051 /* own alerting tone */
3054 /* connect / disconnect audio */
3055 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3056 if (e_ext.own_alerting)
3057 message->param.audiopath = CHANNEL_STATE_HOLD;
3059 message->param.audiopath = CHANNEL_STATE_CONNECT;
3060 message_put(message);
3064 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
3065 message_put(message);
3066 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3068 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
3070 set_tone(portlist, "ringing");
3073 if (e_ext.number[0])
3074 set_tone(portlist, "ringpbx");
3076 set_tone(portlist, "ringing");
3079 /* join MESSAGE_CONNECT */
3080 void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type, union parameter *param)
3082 struct message *message;
3083 struct interface *interface;
3085 new_state(EPOINT_STATE_CONNECT);
3086 // UCPY(e_join_tone, "");
3087 if (e_ext.number[0])
3088 e_dtmf = 1; /* allow dtmf */
3090 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_callerinfo));
3093 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3094 memcpy(&message->param, param, sizeof(union parameter));
3095 /* screen incoming caller id */
3096 interface = interface_first;
3099 if (!strcmp(e_connectinfo.interface, interface->name))
3103 interface = interface->next;
3106 screen(1, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface);
3107 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(e_connectinfo));
3109 /* screen clip if prefix is required */
3110 if (e_ext.number[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0])
3112 SCPY(message->param.connectinfo.id, e_ext.clip_prefix);
3113 SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype));
3114 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
3117 /* use internal caller id */
3118 if (e_ext.number[0] && e_connectinfo.extension[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
3120 SCPY(message->param.connectinfo.id, e_connectinfo.extension);
3121 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
3124 /* handle restricted caller ids */
3125 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);
3126 /* display callerid if desired for extension */
3127 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));
3129 /* use conp, if enabld */
3131 message->param.connectinfo.name[0] = '\0';
3134 message_put(message);
3135 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3137 set_tone(portlist, NULL);
3139 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3140 message->param.audiopath = CHANNEL_STATE_CONNECT;
3141 message_put(message);
3145 /* join MESSAGE_DISCONNECT MESSAGE_RELEASE */
3146 void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *param)
3149 struct message *message;
3150 struct port_list *portlist = NULL;
3153 /* be sure that we are active */
3155 e_tx_state = NOTIFY_STATE_ACTIVE;
3157 /* we are powerdialing, if e_powerdialing is set and limit is not exceeded if given */
3158 if (e_powerdialing && ((e_powercount+1)<e_powerlimit || e_powerlimit<1))
3160 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
3162 /* set time for power dialing */
3163 e_powerdialing = now_d + e_powerdelay; /* set redial in the future */
3166 /* set redial tone */
3167 if (ea_endpoint->ep_portlist)
3171 set_tone(ea_endpoint->ep_portlist, "redial");
3172 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);
3173 /* send proceeding when powerdialing and still setup (avoid dialing timeout) */
3174 if (e_state==EPOINT_STATE_IN_OVERLAP)
3176 new_state(EPOINT_STATE_IN_PROCEEDING);
3177 if (ea_endpoint->ep_portlist)
3179 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3180 message_put(message);
3181 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3183 /* caused the error, that the first knock sound was not there */
3184 /* set_tone(portlist, "proceeding"); */
3186 /* send display of powerdialing */
3187 if (e_ext.display_dialing)
3189 portlist = ea_endpoint->ep_portlist;
3192 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3194 SPRINT(message->param.notifyinfo.display, "Retry %d of %d", e_powercount, e_powerlimit);
3196 SPRINT(message->param.notifyinfo.display, "Retry %d", e_powercount);
3197 message_put(message);
3198 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3199 portlist = portlist->next;
3208 if ((e_state!=EPOINT_STATE_CONNECT
3209 && e_state!=EPOINT_STATE_OUT_DISCONNECT
3210 && e_state!=EPOINT_STATE_IN_OVERLAP
3211 && e_state!=EPOINT_STATE_IN_PROCEEDING
3212 && e_state!=EPOINT_STATE_IN_ALERTING)
3213 || !ea_endpoint->ep_portlist) /* or no port */
3215 process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
3216 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause); /* RELEASE_TYPE, join, port */
3217 return; /* must exit here */
3222 e_join_cause = param->disconnectinfo.cause;
3223 e_join_location = param->disconnectinfo.location;
3226 /* on release we need the audio again! */
3227 if (message_type == MESSAGE_RELEASE)
3230 ea_endpoint->ep_join_id = 0;
3232 /* disconnect and select tone */
3233 new_state(EPOINT_STATE_OUT_DISCONNECT);
3234 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
3235 /* if own_cause, we must release the join */
3236 if (e_ext.own_cause /* own cause */
3237 || !e_join_pattern) /* no patterns */
3239 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);
3240 if (message_type != MESSAGE_RELEASE)
3241 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
3243 } else /* else we enable audio */
3245 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3246 message->param.audiopath = CHANNEL_STATE_CONNECT;
3247 message_put(message);
3249 /* send disconnect message */
3250 SCPY(e_tone, cause);
3251 portlist = ea_endpoint->ep_portlist;
3254 set_tone(portlist, cause);
3255 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
3256 portlist = portlist->next;
3260 /* join MESSAGE_SETUP */
3261 void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, union parameter *param)
3263 struct message *message;
3264 struct interface *interface;
3266 /* if we already in setup state, we just update the dialing with new digits */
3267 if (e_state == EPOINT_STATE_OUT_SETUP
3268 || e_state == EPOINT_STATE_OUT_OVERLAP)
3270 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we are in setup state, so we do overlap dialing.\n", ea_endpoint->ep_serial);
3271 /* if digits changed, what we have already dialed */
3272 if (!!strncmp(e_dialinginfo.id,param->setup.dialinginfo.id,strlen(e_dialinginfo.id)))
3274 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);
3275 /* release all ports */
3276 while((portlist = ea_endpoint->ep_portlist))
3278 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
3279 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
3280 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3281 message_put(message);
3282 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3283 ea_endpoint->free_portlist(portlist);
3286 /* disconnect audio */
3287 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3288 message->param.audiopath = CHANNEL_STATE_HOLD;
3289 message_put(message);
3291 /* get dialing info */
3292 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3293 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3294 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3295 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3296 new_state(EPOINT_STATE_OUT_OVERLAP);
3299 e_redial = now_d + 1; /* set redial one second in the future */
3302 /* if we have a pending redial, so we just adjust the dialing number */
3305 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);
3306 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3309 if (!ea_endpoint->ep_portlist)
3311 PERROR("ERROR: overlap dialing to a NULL port relation\n");
3313 if (ea_endpoint->ep_portlist->next)
3315 PERROR("ERROR: overlap dialing to a port_list port relation\n");
3317 if (e_state == EPOINT_STATE_OUT_SETUP)
3320 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);
3321 SCAT(e_dialing_queue, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3325 /* get what we have not dialed yet */
3326 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));
3327 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
3328 SCPY(message->param.information.id, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3329 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
3330 message_put(message);
3331 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3333 /* always store what we have dialed or queued */
3334 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3338 if (e_state != EPOINT_STATE_IDLE)
3340 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
3343 /* if an internal extension is dialed, copy that number */
3344 if (param->setup.dialinginfo.itype==INFO_ITYPE_ISDN_EXTENSION || param->setup.dialinginfo.itype==INFO_ITYPE_VBOX)
3345 SCPY(e_ext.number, param->setup.dialinginfo.id);
3346 /* if an internal extension is dialed, get extension's info about caller */
3347 if (e_ext.number[0])
3349 if (!read_extension(&e_ext, e_ext.number))
3351 e_ext.number[0] = '\0';
3352 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the called terminal='%s' is not found in directory tree!\n", ea_endpoint->ep_serial, e_ext.number);
3356 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3357 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3358 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3359 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3361 /* screen incoming caller id */
3362 interface = interface_first;
3365 if (!strcmp(e_callerinfo.interface, interface->name))
3369 interface = interface->next;
3372 screen(1, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface);
3374 /* process (voice over) data calls */
3375 if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO)
3377 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) handling data call as audio call: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
3378 memset(&e_capainfo, 0, sizeof(e_capainfo));
3379 e_capainfo.bearer_capa = INFO_BC_AUDIO;
3380 e_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
3381 e_capainfo.bearer_info1 = (options.law=='u')?INFO_INFO1_ULAW:INFO_INFO1_ALAW;
3384 new_state(EPOINT_STATE_OUT_SETUP);
3385 /* call special setup routine */
3389 /* join MESSAGE_mISDNSIGNAL */
3390 void EndpointAppPBX::join_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param)
3392 struct message *message;
3396 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
3397 memcpy(&message->param, param, sizeof(union parameter));
3398 message_put(message);
3399 portlist = portlist->next;
3403 /* join MESSAGE_NOTIFY */
3404 void EndpointAppPBX::join_notify(struct port_list *portlist, int message_type, union parameter *param)
3406 struct message *message;
3409 if (param->notifyinfo.notify)
3411 new_state = track_notify(e_tx_state, param->notifyinfo.notify);
3412 // /* if notification was generated locally, we turn hold music on/off */
3413 // if (param->notifyinfo.local)
3414 // 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)
3419 if (new_state!=NOTIFY_STATE_HOLD && new_state!=NOTIFY_STATE_SUSPEND)
3423 set_tone(portlist, "");
3424 portlist = portlist->next;
3426 portlist = ea_endpoint->ep_portlist;
3431 if (new_state==NOTIFY_STATE_HOLD || new_state==NOTIFY_STATE_SUSPEND)
3435 set_tone(portlist, "hold");
3436 portlist = portlist->next;
3438 portlist = ea_endpoint->ep_portlist;
3443 /* save new state */
3444 e_tx_state = new_state;
3447 /* notify port(s) about it */
3450 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3451 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
3452 /* handle restricted caller ids */
3453 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);
3454 /* display callerid if desired for extension */
3455 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));
3456 message_put(message);
3457 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3458 portlist = portlist->next;
3462 /* JOIN sends messages to the endpoint
3464 void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, union parameter *param)
3466 struct port_list *portlist;
3467 struct message *message;
3471 PERROR("EPOINT(%d) error: JOIN == NULL.\n", ea_endpoint->ep_serial);
3475 portlist = ea_endpoint->ep_portlist;
3477 /* send MESSAGE_DATA to port */
3478 if (message_type == MESSAGE_DATA)
3480 if (join_id == ea_endpoint->ep_join_id) // still linked with JOIN
3482 /* skip if no port relation */
3485 /* skip if more than one port relation */
3488 /* forward audio data to port */
3489 message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3494 // 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);
3495 switch(message_type)
3497 /* JOIN SENDS TONE message */
3499 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received tone message: '%d'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->tone.name);
3500 set_tone(portlist, param->tone.name);
3503 /* JOIN SENDS CRYPT message */
3505 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);
3506 join_crypt(portlist, message_type, param);
3509 /* JOIN sends INFORMATION message */
3510 case MESSAGE_INFORMATION:
3511 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);
3512 join_information(portlist, message_type, param);
3515 /* JOIN sends FACILITY message */
3516 case MESSAGE_FACILITY:
3517 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);
3518 join_facility(portlist, message_type, param);
3521 /* JOIN sends OVERLAP message */
3522 case MESSAGE_OVERLAP:
3523 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);
3524 if (e_state!=EPOINT_STATE_IN_SETUP
3525 && e_state!=EPOINT_STATE_IN_OVERLAP)
3527 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3530 join_overlap(portlist, message_type, param);
3533 /* JOIN sends PROCEEDING message */
3534 case MESSAGE_PROCEEDING:
3535 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);
3536 if(e_state!=EPOINT_STATE_IN_OVERLAP)
3538 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3541 join_proceeding(portlist, message_type, param);
3544 /* JOIN sends ALERTING message */
3545 case MESSAGE_ALERTING:
3546 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);
3547 if (e_state!=EPOINT_STATE_IN_OVERLAP
3548 && e_state!=EPOINT_STATE_IN_PROCEEDING)
3550 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state.\n", ea_endpoint->ep_serial);
3553 join_alerting(portlist, message_type, param);
3556 /* JOIN sends CONNECT message */
3557 case MESSAGE_CONNECT:
3558 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);
3559 if (e_state!=EPOINT_STATE_IN_OVERLAP
3560 && e_state!=EPOINT_STATE_IN_PROCEEDING
3561 && e_state!=EPOINT_STATE_IN_ALERTING)
3563 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
3566 join_connect(portlist, message_type, param);
3569 /* JOIN sends DISCONNECT/RELEASE message */
3570 case MESSAGE_DISCONNECT: /* JOIN disconnect */
3571 case MESSAGE_RELEASE: /* JOIN releases */
3572 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);
3573 join_disconnect_release(message_type, param);
3576 /* JOIN sends SETUP message */
3578 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);
3579 join_setup(portlist, message_type, param);
3582 /* JOIN sends special mISDNSIGNAL message */
3583 case MESSAGE_mISDNSIGNAL: /* isdn message to port */
3584 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);
3585 join_mISDNsignal(portlist, message_type, param);
3589 /* JOIN requests bchannel */
3590 case MESSAGE_BCHANNEL: /* indicates the need of own bchannel access */
3591 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);
3592 /* only one port is expected to be connected to bchannel */
3599 set_tone(portlist, NULL);
3600 message = message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3601 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3605 /* JOIN has pattern available */
3606 case MESSAGE_PATTERN: /* indicating pattern available */
3607 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);
3608 if (!e_join_pattern)
3610 PDEBUG(DEBUG_EPOINT, "-> pattern becomes available\n");
3615 set_tone(portlist, NULL);
3616 portlist = portlist->next;
3618 /* connect our audio tx and rx (blueboxing should be possibe before connect :)*/
3619 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3620 message->param.audiopath = CHANNEL_STATE_CONNECT;
3621 message_put(message);
3622 // /* tell remote epoint to connect audio also, because we like to hear the patterns */
3623 // message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_REMOTE_AUDIO);
3624 // message->param.audiopath = CHANNEL_STATE_CONNECT;
3625 // message_put(message);
3626 // patterns are available, remote already connected audio
3630 /* JOIN has no pattern available */
3631 case MESSAGE_NOPATTERN: /* indicating no pattern available */
3632 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);
3635 PDEBUG(DEBUG_EPOINT, "-> pattern becomes unavailable\n");
3637 /* disconnect our audio tx and rx */
3638 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3639 message->param.audiopath = CHANNEL_STATE_HOLD;
3640 message_put(message);
3645 /* JOIN (dunno at the moment) */
3646 case MESSAGE_REMOTE_AUDIO:
3647 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);
3648 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3649 message->param.audiopath = param->channel;
3650 message_put(message);
3654 /* JOIN sends a notify message */
3655 case MESSAGE_NOTIFY:
3656 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);
3657 join_notify(portlist, message_type, param);
3661 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);
3666 /* pick_join will connect the first incoming call found. the endpoint
3667 * will receivce a MESSAGE_CONNECT.
3669 int match_list(char *list, char *item)
3671 char *end, *next = NULL;
3673 /* no list make matching */
3679 /* eliminate white spaces */
3680 while (*list <= ' ')
3687 /* if end of list is reached, we return */
3688 if (list[0] == '\0')
3690 /* if we have more than one entry (left) */
3691 if ((end = strchr(list, ',')))
3694 next = end = strchr(list, '\0');
3695 while (*(end-1) <= ' ')
3697 /* if string part matches item */
3698 if (!strncmp(list, item, end-list))
3704 void EndpointAppPBX::pick_join(char *extensions)
3706 struct message *message;
3707 struct port_list *portlist;
3709 class EndpointAppPBX *eapp, *found;
3711 class JoinPBX *joinpbx;
3712 struct join_relation *relation;
3715 /* find an endpoint that is ringing internally or vbox with higher priority */
3718 eapp = apppbx_first;
3721 if (eapp!=this && ea_endpoint->ep_portlist)
3723 portlist = eapp->ea_endpoint->ep_portlist;
3726 if ((port = find_port_id(portlist->port_id)))
3728 if (port->p_type == PORT_TYPE_VBOX_OUT)
3730 if (match_list(extensions, eapp->e_ext.number))
3737 if ((port->p_type==PORT_TYPE_DSS1_NT_OUT || port->p_type==PORT_TYPE_DSS1_TE_OUT)
3738 && port->p_state==PORT_STATE_OUT_ALERTING)
3739 if (match_list(extensions, eapp->e_ext.number))
3744 portlist = portlist->next;
3752 /* if no endpoint found */
3755 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);
3757 set_tone(ea_endpoint->ep_portlist, "cause_10");
3758 message_disconnect_port(ea_endpoint->ep_portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
3759 new_state(EPOINT_STATE_OUT_DISCONNECT);
3764 if (ea_endpoint->ep_join_id)
3766 PERROR("EPOINT(%d) we already have a join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3769 if (!eapp->ea_endpoint->ep_join_id)
3771 PERROR("EPOINT(%d) ringing endpoint has no join.\n", ea_endpoint->ep_serial);
3774 join = find_join_id(eapp->ea_endpoint->ep_join_id);
3777 PERROR("EPOINT(%d) ringing endpoint's join not found.\n", ea_endpoint->ep_serial);
3780 if (join->j_type != JOIN_TYPE_PBX)
3782 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ringing endpoint's join is not a PBX join, so we must reject.\n", ea_endpoint->ep_serial);
3785 joinpbx = (class JoinPBX *)join;
3786 relation = joinpbx->j_relation;
3789 PERROR("EPOINT(%d) ringing endpoint's join has no relation. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3792 while (relation->epoint_id != eapp->ea_endpoint->ep_serial)
3794 relation = relation->next;
3797 PERROR("EPOINT(%d) ringing endpoint's join has no relation to that join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3802 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found ringing endpoint: %d.\n", ea_endpoint->ep_serial, eapp->ea_endpoint->ep_serial);
3804 if (options.deb & DEBUG_EPOINT)
3806 class Join *debug_c = join_first;
3807 class Endpoint *debug_e = epoint_first;
3808 class Port *debug_p = port_first;
3810 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(before)");
3812 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3815 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3816 debug_c = debug_c->next;
3818 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3821 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3822 debug_e = debug_e->next;
3824 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3827 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld (active)\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3828 debug_p = debug_p->next;
3833 ea_endpoint->ep_join_id = eapp->ea_endpoint->ep_join_id; /* we get the join */
3834 relation->epoint_id = ea_endpoint->ep_serial; /* the join gets us */
3835 eapp->ea_endpoint->ep_join_id = 0; /* the ringing endpoint will get disconnected */
3837 /* connnecting our endpoint */
3838 new_state(EPOINT_STATE_CONNECT);
3840 set_tone(ea_endpoint->ep_portlist, NULL);
3842 /* now we send a release to the ringing endpoint */
3843 message = message_create(ea_endpoint->ep_join_id, eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3844 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
3845 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3846 message_put(message);
3848 /* we send a connect to the join with our caller id */
3849 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CONNECT);
3850 SCPY(message->param.connectinfo.id, e_callerinfo.id);
3851 message->param.connectinfo.present = e_callerinfo.present;
3852 message->param.connectinfo.screen = e_callerinfo.screen;
3853 message->param.connectinfo.itype = e_callerinfo.itype;
3854 message->param.connectinfo.ntype = e_callerinfo.ntype;
3855 message_put(message);
3857 /* we send a connect to our port with the remote callerid */
3858 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3859 SCPY(message->param.connectinfo.id, eapp->e_callerinfo.id);
3860 message->param.connectinfo.present = eapp->e_callerinfo.present;
3861 message->param.connectinfo.screen = eapp->e_callerinfo.screen;
3862 message->param.connectinfo.itype = eapp->e_callerinfo.itype;
3863 message->param.connectinfo.ntype = eapp->e_callerinfo.ntype;
3864 /* handle restricted caller ids */
3865 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);
3866 /* display callerid if desired for extension */
3867 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));
3868 message_put(message);
3870 /* we send a connect to the audio path (not for vbox) */
3871 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3872 message->param.audiopath = CHANNEL_STATE_CONNECT;
3873 message_put(message);
3875 /* beeing paranoid, we make call update */
3876 joinpbx->j_updatebridge = 1;
3878 if (options.deb & DEBUG_EPOINT)
3880 class Join *debug_c = join_first;
3881 class Endpoint *debug_e = epoint_first;
3882 class Port *debug_p = port_first;
3884 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(after)");
3886 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3889 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3890 debug_c = debug_c->next;
3892 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3895 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3896 debug_e = debug_e->next;
3898 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3901 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3902 debug_p = debug_p->next;
3908 /* join calls (look for a join that is on hold (same isdn interface/terminal))
3910 void EndpointAppPBX::join_join(void)
3912 struct message *message;
3913 struct join_relation *our_relation, *other_relation;
3914 struct join_relation **our_relation_pointer, **other_relation_pointer;
3915 class Join *our_join, *other_join;
3916 class JoinPBX *our_joinpbx, *other_joinpbx;
3917 class EndpointAppPBX *other_eapp; class Endpoint *temp_epoint;
3918 class Port *our_port, *other_port;
3919 class Pdss1 *our_pdss1, *other_pdss1;
3921 /* are we a candidate to join a join */
3922 our_join = find_join_id(ea_endpoint->ep_join_id);
3925 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3928 if (our_join->j_type != JOIN_TYPE_PBX)
3930 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: join is not a pbx join.\n", ea_endpoint->ep_serial);
3933 our_joinpbx = (class JoinPBX *)our_join;
3934 if (!ea_endpoint->ep_portlist)
3936 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
3939 if (!e_ext.number[0])
3941 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
3944 our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
3947 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
3950 if ((our_port->p_type&PORT_CLASS_mISDN_MASK) != PORT_CLASS_mISDN_DSS1)
3952 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not isdn.\n", ea_endpoint->ep_serial);
3955 our_pdss1 = (class Pdss1 *)our_port;
3957 /* find an endpoint that is on hold and has the same mISDNport that we are on */
3958 other_eapp = apppbx_first;
3961 if (other_eapp == this)
3963 other_eapp = other_eapp->next;
3966 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);
3967 if (other_eapp->e_ext.number[0] /* has terminal */
3968 && other_eapp->ea_endpoint->ep_portlist /* has port */
3969 && other_eapp->ea_endpoint->ep_join_id) /* has join */
3971 other_port = find_port_id(other_eapp->ea_endpoint->ep_portlist->port_id);
3972 if (other_port) /* port still exists */
3974 if (other_port->p_type==PORT_TYPE_DSS1_NT_OUT
3975 || other_port->p_type==PORT_TYPE_DSS1_NT_IN) /* port is isdn nt-mode */
3977 other_pdss1 = (class Pdss1 *)other_port;
3978 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);
3979 if (other_pdss1->p_m_hold /* port is on hold */
3980 && other_pdss1->p_m_mISDNport == our_pdss1->p_m_mISDNport /* same isdn interface */
3981 && other_pdss1->p_m_d_ces == our_pdss1->p_m_d_ces) /* same tei+sapi */
3985 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of other type!\n", ea_endpoint->ep_serial);
3989 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port doesn't exist enymore.\n", ea_endpoint->ep_serial);
3992 other_eapp = other_eapp->next;
3996 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn interface with port on hold.\n", ea_endpoint->ep_serial);
3999 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port on hold found.\n", ea_endpoint->ep_serial);
4001 /* if we have the same join */
4002 if (other_eapp->ea_endpoint->ep_join_id == ea_endpoint->ep_join_id)
4004 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we an the other have the same join.\n", ea_endpoint->ep_serial);
4007 other_join = find_join_id(other_eapp->ea_endpoint->ep_join_id);
4010 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
4013 if (other_join->j_type != JOIN_TYPE_PBX)
4015 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join is not a pbx join.\n", ea_endpoint->ep_serial);
4018 other_joinpbx = (class JoinPBX *)other_join;
4019 if (our_joinpbx->j_partyline && other_joinpbx->j_partyline)
4021 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both joins are partylines.\n", ea_endpoint->ep_serial);
4025 /* remove relation to endpoint for join on hold */
4026 other_relation = other_joinpbx->j_relation;
4027 other_relation_pointer = &other_joinpbx->j_relation;
4028 while(other_relation)
4030 if (other_relation->epoint_id == other_eapp->ea_endpoint->ep_serial)
4032 /* detach other endpoint on hold */
4033 *other_relation_pointer = other_relation->next;
4034 FREE(other_relation, sizeof(struct join_relation));
4036 other_relation = *other_relation_pointer;
4037 other_eapp->ea_endpoint->ep_join_id = NULL;
4041 /* change join/hold pointer of endpoint to the new join */
4042 temp_epoint = find_epoint_id(other_relation->epoint_id);
4045 if (temp_epoint->ep_join_id == other_join->j_serial)
4046 temp_epoint->ep_join_id = our_join->j_serial;
4049 other_relation_pointer = &other_relation->next;
4050 other_relation = other_relation->next;
4052 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint on hold removed, other enpoints on join relinked (to our join).\n", ea_endpoint->ep_serial);
4054 /* join call relations */
4055 our_relation = our_joinpbx->j_relation;
4056 our_relation_pointer = &our_joinpbx->j_relation;
4059 our_relation_pointer = &our_relation->next;
4060 our_relation = our_relation->next;
4062 *our_relation_pointer = other_joinpbx->j_relation;
4063 other_joinpbx->j_relation = NULL;
4064 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) relations joined.\n", ea_endpoint->ep_serial);
4066 /* release endpoint on hold */
4067 message = message_create(other_joinpbx->j_serial, other_eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
4068 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */
4069 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
4070 message_put(message);
4072 /* if we are not a partyline, we get partyline state from other join */
4073 our_joinpbx->j_partyline += other_joinpbx->j_partyline;
4075 /* remove empty join */
4077 PDEBUG(DEBUG_EPOINT, "EPOINT(%d)d-join completely removed!\n");
4079 /* mixer must update */
4080 our_joinpbx->j_updatebridge = 1; /* update mixer flag */
4082 /* we send a retrieve to that endpoint */
4083 // mixer will update the hold-state of the join and send it to the endpoints is changes
4087 /* check if we have an external call
4088 * this is used to check for encryption ability
4090 int EndpointAppPBX::check_external(char **errstr, class Port **port)
4092 struct join_relation *relation;
4094 class JoinPBX *joinpbx;
4095 class Endpoint *epoint;
4097 /* some paranoia check */
4098 if (!ea_endpoint->ep_portlist)
4100 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we have no port.\n", ea_endpoint->ep_serial);
4101 *errstr = "No Call";
4104 if (!e_ext.number[0])
4106 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we are not internal extension.\n", ea_endpoint->ep_serial);
4107 *errstr = "No Call";
4111 /* check if we have a join with 2 parties */
4112 join = find_join_id(ea_endpoint->ep_join_id);
4115 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have currently no join.\n", ea_endpoint->ep_serial);
4116 *errstr = "No Call";
4119 if (join->j_type != JOIN_TYPE_PBX)
4121 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join is not a pbx join.\n", ea_endpoint->ep_serial);
4122 *errstr = "No PBX Call";
4125 joinpbx = (class JoinPBX *)join;
4126 relation = joinpbx->j_relation;
4129 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no relation.\n", ea_endpoint->ep_serial);
4130 *errstr = "No Call";
4133 if (!relation->next)
4135 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd relation.\n", ea_endpoint->ep_serial);
4136 *errstr = "No Call";
4139 if (relation->next->next)
4141 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has more than two relations.\n", ea_endpoint->ep_serial);
4142 *errstr = "Err: Conference";
4145 if (relation->epoint_id == ea_endpoint->ep_serial)
4147 relation = relation->next;
4148 if (relation->epoint_id == ea_endpoint->ep_serial)
4150 PERROR("EPOINT(%d) SOFTWARE ERROR: both join relations are related to our endpoint.\n", ea_endpoint->ep_serial);
4151 *errstr = "Software Error";
4156 /* check remote port for external call */
4157 epoint = find_epoint_id(relation->epoint_id);
4160 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd endpoint.\n", ea_endpoint->ep_serial);
4161 *errstr = "No Call";
4164 if (!epoint->ep_portlist)
4166 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not port.\n", ea_endpoint->ep_serial);
4167 *errstr = "No Call";
4170 *port = find_port_id(epoint->ep_portlist->port_id);
4173 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has an none existing port.\n", ea_endpoint->ep_serial);
4174 *errstr = "No Call";
4177 if (((*port)->p_type&PORT_CLASS_mISDN_MASK)!=PORT_CLASS_mISDN_DSS1) /* port is not external isdn */
4179 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not an external port.\n", ea_endpoint->ep_serial);
4180 *errstr = "No Ext Call";
4183 if ((*port)->p_state != PORT_STATE_CONNECT)
4185 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint's port is not in connected state.\n", ea_endpoint->ep_serial);
4186 *errstr = "No Ext Connect";
4192 void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsigned long port_id, int dir)
4194 char *logtext = "unknown";
4197 switch(message_type)
4200 trace_header("SETUP", dir);
4201 if (dir == DIRECTION_OUT)
4202 add_trace("to", NULL, "CH(%lu)", port_id);
4203 if (dir == DIRECTION_IN)
4204 add_trace("from", NULL, "CH(%lu)", port_id);
4205 if (param->setup.callerinfo.extension[0])
4206 add_trace("extension", NULL, "%s", param->setup.callerinfo.extension);
4207 add_trace("caller id", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype));
4208 switch(param->setup.callerinfo.present)
4210 case INFO_PRESENT_RESTRICTED:
4211 add_trace("caller id", "present", "restricted");
4213 case INFO_PRESENT_ALLOWED:
4214 add_trace("caller id", "present", "allowed");
4217 add_trace("caller id", "present", "not available");
4219 if (param->setup.redirinfo.id[0])
4221 add_trace("redir'ing", "number", "%s", numberrize_callerinfo(param->setup.redirinfo.id, param->setup.redirinfo.ntype));
4222 switch(param->setup.redirinfo.present)
4224 case INFO_PRESENT_RESTRICTED:
4225 add_trace("redir'ing", "present", "restricted");
4227 case INFO_PRESENT_ALLOWED:
4228 add_trace("redir'ing", "present", "allowed");
4231 add_trace("redir'ing", "present", "not available");
4234 if (param->setup.dialinginfo.id[0])
4235 add_trace("dialing", NULL, "%s", param->setup.dialinginfo.id);
4239 case MESSAGE_OVERLAP:
4240 trace_header("SETUP ACKNOWLEDGE", dir);
4241 if (dir == DIRECTION_OUT)
4242 add_trace("to", NULL, "CH(%lu)", port_id);
4243 if (dir == DIRECTION_IN)
4244 add_trace("from", NULL, "CH(%lu)", port_id);
4248 case MESSAGE_PROCEEDING:
4249 trace_header("PROCEEDING", dir);
4250 if (dir == DIRECTION_OUT)
4251 add_trace("to", NULL, "CH(%lu)", port_id);
4252 if (dir == DIRECTION_IN)
4253 add_trace("from", NULL, "CH(%lu)", port_id);
4257 case MESSAGE_ALERTING:
4258 trace_header("ALERTING", dir);
4259 if (dir == DIRECTION_OUT)
4260 add_trace("to", NULL, "CH(%lu)", port_id);
4261 if (dir == DIRECTION_IN)
4262 add_trace("from", NULL, "CH(%lu)", port_id);
4266 case MESSAGE_CONNECT:
4267 trace_header("CONNECT", dir);
4268 if (dir == DIRECTION_OUT)
4269 add_trace("to", NULL, "CH(%lu)", port_id);
4270 if (dir == DIRECTION_IN)
4271 add_trace("from", NULL, "CH(%lu)", port_id);
4272 if (param->connectinfo.extension[0])
4273 add_trace("extension", NULL, "%s", param->connectinfo.extension);
4274 add_trace("connect id", "number", "%s", numberrize_callerinfo(param->connectinfo.id, param->connectinfo.ntype));
4275 switch(param->connectinfo.present)
4277 case INFO_PRESENT_RESTRICTED:
4278 add_trace("connect id", "present", "restricted");
4280 case INFO_PRESENT_ALLOWED:
4281 add_trace("connect id", "present", "allowed");
4284 add_trace("connect id", "present", "not available");
4289 case MESSAGE_DISCONNECT:
4290 case MESSAGE_RELEASE:
4291 if (message_type == MESSAGE_DISCONNECT)
4292 trace_header("DISCONNECT", dir);
4294 trace_header("RELEASE", dir);
4295 if (dir == DIRECTION_OUT)
4296 add_trace("to", NULL, "CH(%lu)", port_id);
4297 if (dir == DIRECTION_IN)
4298 add_trace("from", NULL, "CH(%lu)", port_id);
4299 add_trace("cause", "value", "%d", param->disconnectinfo.cause);
4300 switch(param->disconnectinfo.location)
4303 add_trace("cause", "location", "0-User");
4305 case LOCATION_PRIVATE_LOCAL:
4306 add_trace("cause", "location", "1-Local-PBX");
4308 case LOCATION_PUBLIC_LOCAL:
4309 add_trace("cause", "location", "2-Local-Exchange");
4311 case LOCATION_TRANSIT:
4312 add_trace("cause", "location", "3-Transit");
4314 case LOCATION_PUBLIC_REMOTE:
4315 add_trace("cause", "location", "4-Remote-PBX");
4317 case LOCATION_PRIVATE_REMOTE:
4318 add_trace("cause", "location", "5-Remote-Exchange");
4320 case LOCATION_INTERNATIONAL:
4321 add_trace("cause", "location", "7-International-Exchange");
4323 case LOCATION_BEYOND:
4324 add_trace("cause", "location", "10-Beyond-Interworking");
4327 add_trace("cause", "location", "%d", param->disconnectinfo.location);
4332 case MESSAGE_NOTIFY:
4333 switch(param->notifyinfo.notify)
4339 logtext = "USER_SUSPENDED";
4342 logtext = "BEARER_SERVICE_CHANGED";
4345 logtext = "USER_RESUMED";
4348 logtext = "CONFERENCE_ESTABLISHED";
4351 logtext = "CONFERENCE_DISCONNECTED";
4354 logtext = "OTHER_PARTY_ADDED";
4357 logtext = "ISOLATED";
4360 logtext = "REATTACHED";
4363 logtext = "OTHER_PARTY_ISOLATED";
4366 logtext = "OTHER_PARTY_REATTACHED";
4369 logtext = "OTHER_PARTY_SPLIT";
4372 logtext = "OTHER_PARTY_DISCONNECTED";
4375 logtext = "CONFERENCE_FLOATING";
4378 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
4381 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
4384 logtext = "CALL_IS_A_WAITING_CALL";
4387 logtext = "DIVERSION_ACTIVATED";
4390 logtext = "RESERVED_CT_1";
4393 logtext = "RESERVED_CT_2";
4396 logtext = "REVERSE_CHARGING";
4399 logtext = "REMOTE_HOLD";
4402 logtext = "REMOTE_RETRIEVAL";
4405 logtext = "CALL_IS_DIVERTING";
4408 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
4412 trace_header("NOTIFY", dir);
4413 if (dir == DIRECTION_OUT)
4414 add_trace("to", NULL, "CH(%lu)", port_id);
4415 if (dir == DIRECTION_IN)
4416 add_trace("from", NULL, "CH(%lu)", port_id);
4417 if (param->notifyinfo.notify)
4418 add_trace("indicator", NULL, "%s", logtext);
4419 if (param->notifyinfo.id[0])
4421 add_trace("redir'on", "number", "%s", numberrize_callerinfo(param->notifyinfo.id, param->notifyinfo.ntype));
4422 switch(param->notifyinfo.present)
4424 case INFO_PRESENT_RESTRICTED:
4425 add_trace("redir'on", "present", "restricted");
4427 case INFO_PRESENT_ALLOWED:
4428 add_trace("redir'on", "present", "allowed");
4431 add_trace("redir'on", "present", "not available");
4434 if (param->notifyinfo.display[0])
4435 add_trace("display", NULL, "%s", param->notifyinfo.display);
4439 case MESSAGE_INFORMATION:
4440 trace_header("INFORMATION", dir);
4441 if (dir == DIRECTION_OUT)
4442 add_trace("to", NULL, "CH(%lu)", port_id);
4443 if (dir == DIRECTION_IN)
4444 add_trace("from", NULL, "CH(%lu)", port_id);
4445 add_trace("dialing", NULL, "%s", param->information.id);
4449 case MESSAGE_FACILITY:
4450 trace_header("FACILITY", dir);
4451 if (dir == DIRECTION_OUT)
4452 add_trace("to", NULL, "CH(%lu)", port_id);
4453 if (dir == DIRECTION_IN)
4454 add_trace("from", NULL, "CH(%lu)", port_id);
4459 trace_header("TONE", dir);
4460 if (dir == DIRECTION_OUT)
4461 add_trace("to", NULL, "CH(%lu)", port_id);
4462 if (dir == DIRECTION_IN)
4463 add_trace("from", NULL, "CH(%lu)", port_id);
4464 if (param->tone.name[0])
4466 add_trace("directory", NULL, "%s", param->tone.dir[0]?param->tone.dir:"default");
4467 add_trace("name", NULL, "%s", param->tone.name);
4469 add_trace("off", NULL, NULL);
4473 case MESSAGE_SUSPEND:
4474 case MESSAGE_RESUME:
4475 if (message_type == MESSAGE_SUSPEND)
4476 trace_header("SUSPEND", dir);
4478 trace_header("RESUME", dir);
4479 if (dir == DIRECTION_OUT)
4480 add_trace("to", NULL, "CH(%lu)", port_id);
4481 if (dir == DIRECTION_IN)
4482 add_trace("from", NULL, "CH(%lu)", port_id);
4483 if (param->parkinfo.len)
4484 add_trace("length", NULL, "%d", param->parkinfo.len);
4489 case MESSAGE_BCHANNEL:
4490 trace_header("BCHANNEL", dir);
4491 switch(param->bchannel.type)
4493 case BCHANNEL_REQUEST:
4494 add_trace("type", NULL, "request");
4496 case BCHANNEL_ASSIGN:
4497 add_trace("type", NULL, "assign");
4499 case BCHANNEL_ASSIGN_ACK:
4500 add_trace("type", NULL, "assign_ack");
4502 case BCHANNEL_REMOVE:
4503 add_trace("type", NULL, "remove");
4505 case BCHANNEL_REMOVE_ACK:
4506 add_trace("type", NULL, "remove_ack");
4509 if (param->bchannel.addr)
4510 add_trace("address", NULL, "%x", param->bchannel.addr);
4516 PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message_type);
4520 void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cause, int location, char *display)
4522 struct message *message;
4526 if (!portlist->port_id)
4529 if (!e_connectedmode)
4531 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT);
4532 message->param.disconnectinfo.cause = cause;
4533 message->param.disconnectinfo.location = location;
4535 SCPY(message->param.disconnectinfo.display, display);
4537 SCPY(message->param.disconnectinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4540 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
4542 SCPY(message->param.notifyinfo.display, display);
4544 SCPY(message->param.notifyinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4546 message_put(message);
4547 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);