1 /*****************************************************************************\
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
8 ** The EndpointAppPBX implements PBX4Linux **
10 \*****************************************************************************/
15 #include <sys/types.h>
24 class EndpointAppPBX *apppbx_first = NULL;
27 * EndpointAppPBX constructor
29 EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint) : EndpointApp(epoint)
31 class EndpointAppPBX **apppointer;
33 /* add application to chain */
35 apppointer = &apppbx_first;
37 apppointer = &((*apppointer)->next);
41 memset(&e_ext, 0, sizeof(struct extension));
42 e_ext.rights = 4; /* international */
43 e_ext.rxvol = e_ext.txvol = 256;
44 e_state = EPOINT_STATE_IDLE;
45 e_ext.number[0] = '\0';
46 e_extension_interface[0] = '\0';
47 memset(&e_callerinfo, 0, sizeof(struct caller_info));
48 memset(&e_dialinginfo, 0, sizeof(struct dialing_info));
49 memset(&e_connectinfo, 0, sizeof(struct connect_info));
50 memset(&e_redirinfo, 0, sizeof(struct redir_info));
51 memset(&e_capainfo, 0, sizeof(struct capa_info));
54 e_ruleset = ruleset_main;
56 e_rule = e_ruleset->rule_first;
61 e_match_to_action = NULL;
63 e_extdialing = e_dialinginfo.number;
67 // e_call_tone[0] = e_hold_tone[0] = '\0';
68 e_call_pattern /*= e_hold_pattern*/ = 0;
71 e_adminid = 0; // will be set, if call was initiated via admin socket
76 e_cbdialing[0] = '\0';
79 memset(&e_callbackinfo, 0, sizeof(struct caller_info));
86 e_password_timeout = 0;
87 e_multipoint_cause = CAUSE_NOUSER;
88 e_multipoint_location = LOCATION_PRIVATE_LOCAL;
89 e_dialing_queue[0] = '\0';
91 e_crypt_state = CM_ST_NULL;
92 e_crypt_keyengine_busy = 0;
93 e_crypt_info[0] = '\0';
96 e_tx_state = NOTIFY_STATE_ACTIVE;
97 e_rx_state = NOTIFY_STATE_ACTIVE;
98 e_call_cause = e_call_location = 0;
99 /*********************************
100 *********************************
101 ********* ATTENTION *************
102 *********************************
103 *********************************/
104 /* if you add new values, that must be initialized, also check if they must
105 * be initialized when doing callback
111 * EpointAppPBX destructor
113 EndpointAppPBX::~EndpointAppPBX(void)
115 class EndpointAppPBX *temp, **tempp;
119 tempp = &apppbx_first;
130 PERROR("error: endpoint not in endpoint's list, exitting.\n");
139 * trace header for application
141 void EndpointAppPBX::trace_header(char *name, int direction)
143 char msgtext[sizeof(trace.name)];
152 if (direction == DIRECTION_OUT)
153 SCAT(msgtext, " N->U");
155 SCAT(msgtext, " N<-U");
158 if (direction == DIRECTION_OUT)
159 SCAT(msgtext, " U->N");
161 SCAT(msgtext, " U<-N");
165 /* init trace with given values */
168 nationalize(e_callerinfo.id, e_callerinfo.ntype),
169 e_dialinginfo.number,
178 /* set new endpoint state
180 void EndpointAppPBX::new_state(int state)
182 if (e_state != state)
184 trace_header("NEW STATE", DIRECTION_NONE);
185 add_trace("state", "old", "%s", state_name[e_state]);
186 add_trace("state", "new", "%s", state_name[state]);
193 * out==0: incomming caller id, out==1: outgoing caller id
195 void EndpointAppPBX::screen(int out, char *id, int idsize, int *type, int *present)
197 struct interface *interface;
199 interface = interface_first;
202 if (!strcmp(e_callerinfo.interface, interface->name))
206 interface = interface->next;
211 /* screen incoming caller id */
214 /* check for MSN numbers, use first MSN if no match */
216 ifmsn = interface->ifmsn;
221 if (!strcmp(ifmns->mns, id))
227 if (!ifmns && mns1) // not in list, first msn given
228 UNCPY(id, msn1, idsize);
232 /* check screen list */
234 iscreen = interface->ifscreen_out;
236 iscreen = interface->ifscreen_in;
239 if (ifcreen->match_type==-1 || ifscreen->match_type==*type)
240 if (ifcreen->match_present==-1 || ifscreen->match_present==*present)
242 if (strchr(ifcreen->match_id,'%'))
244 if (!strncmp(ifscreen->match_id, id, strchr(ifscreen->match_id,'%')-ifscreen->match_id))
248 if (!strcmp(ifscreen->match_id, id))
252 ifscreen = ifscreen->next;
254 if (ifscreen) // match
256 if (ifscren->result_type != -1)
257 *type = ifscreen->result_type;
258 if (ifscren->result_present != -1)
259 *present = ifscreen->result_present;
260 if (strchr(ifscreen->match_id,'%'))
262 SCPY(suffix, strchr(ifscreen->match_id,'%') - ifscreen->match_id + id);
263 UNCPY(id, ifscreen->result_id);
265 if (strchr(ifscreen->result_id,'%'))
267 *strchr(ifscreen->result_id,'%') = '\0';
268 UNCAT(id, suffix, idsize);
273 UNCPY(id, ifscreen->result_id, idsize);
280 /* release call and port (as specified)
282 void EndpointAppPBX::release(int release, int calllocation, int callcause, int portlocation, int portcause)
284 struct port_list *portlist;
285 struct message *message;
289 /* message to test call */
290 admin_call_response(e_adminid, ADMIN_CALL_RELEASE, "", callcause, calllocation, 0);
292 /* if a release is pending */
293 if (release==RELEASE_CALL || release==RELEASE_ALL || release==RELEASE_PORT_CALLONLY)
295 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): do pending release (callcause %d location %d)\n", ea_endpoint->ep_serial, callcause, calllocation);
296 if (ea_endpoint->ep_call_id)
298 call = find_call_id(ea_endpoint->ep_call_id);
300 call->release(ea_endpoint->ep_serial, 0, calllocation, callcause);
302 ea_endpoint->ep_call_id = 0;
305 if (release != RELEASE_PORT_CALLONLY)
308 call_release(e_hold_id, ea_endpoint->ep_serial, 1, calllocation, callcause);
313 if (release==RELEASE_ALL || release==RELEASE_PORT_CALLONLY)
315 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release (portcause %d portlocation)\n", ea_endpoint->ep_serial, portcause, portlocation);
316 while((portlist = ea_endpoint->ep_portlist))
318 if (portlist->port_id)
320 SPRINT(cause, "cause_%02x", portcause);
321 set_tone(portlist, cause);
322 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
323 message->param.disconnectinfo.cause = portcause;
324 message->param.disconnectinfo.location = portlocation;
325 message_put(message);
328 ea_endpoint->free_portlist(portlist);
331 /* if callback is enabled, call back with the given caller id */
334 /* reset some stuff */
335 new_state(EPOINT_STATE_IDLE);
336 memset(&e_connectinfo, 0, sizeof(struct connect_info));
337 memset(&e_redirinfo, 0, sizeof(struct redir_info));
338 e_start = e_stop = 0;
339 e_ruleset = ruleset_main;
341 e_rule = e_ruleset->rule_first;
343 e_action_timeout = 0;
345 e_match_to_action = NULL;
347 e_extdialing = e_dialinginfo.number;
354 e_multipoint_cause = CAUSE_NOUSER;
355 e_multipoint_location = LOCATION_PRIVATE_LOCAL;
356 e_dialing_queue[0] = '\0';
358 e_crypt_state = CM_ST_NULL;
359 e_crypt_keyengine_busy = 0;
360 e_crypt_info[0] = '\0';
364 e_tx_state = NOTIFY_STATE_ACTIVE;
365 e_rx_state = NOTIFY_STATE_ACTIVE;
366 e_call_cause = e_call_location = 0;
368 /* the caller info of the callback user */
369 memcpy(&e_callbackinfo, &e_callerinfo, sizeof(e_callbackinfo));
370 memset(&e_dialinginfo, 0, sizeof(e_dialinginfo));
371 /* create dialing by callerinfo */
372 if (e_ext.number[0] && e_extension_interface[0])
374 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to internal: %s interface %s\n", ea_endpoint->ep_serial, e_ext.number, e_extension_interface);
375 /* create callback to the current terminal */
376 SCPY(e_dialinginfo.number, e_ext.number);
377 SCPY(e_dialinginfo.interfaces, e_extension_interface);
378 e_dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
379 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
384 SCPY(e_dialinginfo.number, e_cbto);
387 /* numberrize caller id and use it to dial to the callback */
388 SCPY(e_dialinginfo.number, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype));
390 e_dialinginfo.itype = INFO_ITYPE_ISDN;
391 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
392 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to external: %s\n", ea_endpoint->ep_serial, e_dialinginfo.number);
397 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release of epoint itself.\n", ea_endpoint->ep_serial);
398 ea_endpoint->ep_use--; /* when e_lock is 0, the endpoint will be deleted */
404 /* cancel callerid if restricted, unless anon-ignore is enabled at extension or port is of type external (so called police gets caller id :)*/
405 void apply_callerid_restriction(int anon_ignore, int port_type, char *id, int *ntype, int *present, int *screen, char *voip, char *intern, char *name)
407 PDEBUG(DEBUG_EPOINT, "id='%s' ntype=%d present=%d screen=%d voip='%s' intern='%s' name='%s'\n", (id)?id:"NULL", (ntype)?*ntype:-1, (present)?*present:-1, (screen)?*screen:-1, (voip)?voip:"NULL", (intern)?intern:"NULL", (name)?name:"NULL");
409 /* caller id is not restricted, so we do nothing */
410 if (*present != INFO_PRESENT_RESTRICTED)
413 /* only extensions are restricted */
419 /* if we enabled anonymouse ignore */
423 /* else we remove the caller id */
427 *ntype = INFO_NTYPE_UNKNOWN;
429 // *screen = INFO_SCREEN_USER;
430 // maybe we should not make voip address anonymous
433 // maybe it's no fraud to present internal id
440 /* used display message to display callerid as available */
441 char *EndpointAppPBX::apply_callerid_display(char *id, int itype, int ntype, int present, int screen, char *voip, char *intern, char *name)
443 static char display[81];
446 char *cid = numberrize_callerinfo(id, ntype);
448 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) id='%s' itype=%d ntype=%d present=%d screen=%d voip='%s' intern='%s' name='%s'\n", ea_endpoint->ep_serial, (id)?id:"NULL", itype, ntype, present, screen, (voip)?voip:"NULL", (intern)?intern:"NULL", (name)?name:"NULL");
459 /* NOTE: is caller is is not available for this extesion, it has been removed by apply_callerid_restriction already */
461 /* internal extension's caller id */
462 if (intern[0] && e_ext.display_int)
465 SCAT(display, intern);
468 if (itype == INFO_ITYPE_VBOX)
469 SCAT(display, "(vbox)");
471 SCAT(display, "(int)");
474 /* external caller id */
475 if (!intern[0] && !voip[0] && e_ext.display_ext)
481 if (present == INFO_PRESENT_RESTRICTED)
482 SCAT(display, "anonymous");
484 SCAT(display, "unknown");
492 if (voip[0] && e_ext.display_voip)
494 if (!display[0] && cid[0])
501 /* display if callerid is anonymouse but available due anon-ignore */
502 if (e_ext.display_anon && present==INFO_PRESENT_RESTRICTED)
505 SCAT(display, "unknown");
508 SCAT(display, " anon");
511 /* display if callerid is anonymouse but available due anon-ignore */
512 if (e_ext.display_fake && screen==INFO_SCREEN_USER && present!=INFO_PRESENT_NULL)
518 if (present == INFO_PRESENT_RESTRICTED)
519 SCAT(display, "anonymous");
521 SCAT(display, "unknown");
526 SCAT(display, " fake");
530 if (name[0] && e_ext.display_name)
532 if (!display[0] && cid[0])
543 * uses the current state to notify activity
545 void EndpointAppPBX::notify_active(void)
547 struct port_list *portlist = ea_endpoint->ep_portlist;
548 struct message *message;
553 case NOTIFY_STATE_ACTIVE:
554 /* we are already active, so we don't do anything */
557 case NOTIFY_STATE_SUSPEND:
558 notify = INFO_NOTIFY_USER_RESUMED;
561 set_tone(portlist, NULL);
562 portlist = portlist->next;
564 portlist = ea_endpoint->ep_portlist;
567 case NOTIFY_STATE_HOLD:
568 notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
571 set_tone(portlist, NULL);
572 portlist = portlist->next;
574 portlist = ea_endpoint->ep_portlist;
577 case NOTIFY_STATE_CONFERENCE:
578 notify = INFO_NOTIFY_CONFERENCE_DISCONNECTED;
581 set_tone(portlist, NULL);
582 portlist = portlist->next;
584 portlist = ea_endpoint->ep_portlist;
588 PERROR("unknown e_tx_state = %d\n", e_tx_state);
594 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
595 message->param.notifyinfo.notify = notify;
596 message_put(message);
598 portlist = portlist->next;
604 * keypad functions during call. one example to use this is to put a call on hold or start a conference
606 void EndpointAppPBX::keypad_function(char digit)
609 /* we must be in a call, in order to send messages to the call */
610 if (e_ext.number[0] == '\0')
612 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) IGNORING keypad received not from extension.\n", ea_endpoint->ep_serial);
618 /* join conference */
620 if (ea_endpoint->ep_call_id == 0)
622 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad received during connect but not during a call.\n", ea_endpoint->ep_serial);
625 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join call with call on hold\n", ea_endpoint->ep_serial);
631 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) shared key encryption selected.\n", ea_endpoint->ep_serial);
635 /* crypt key-exchange */
637 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) key exchange encryption selected.\n", ea_endpoint->ep_serial);
643 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) encryption off selected.\n", ea_endpoint->ep_serial);
648 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) unsupported keypad digit '%c'.\n", ea_endpoint->ep_serial, digit);
653 /* set tone pattern for port */
654 void EndpointAppPBX::set_tone(struct port_list *portlist, char *tone)
656 struct message *message;
661 /* store for suspended processes */
666 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no endpoint to notify tone.\n", ea_endpoint->ep_serial);
670 if (e_call_pattern /* pattern are provided */
671 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_SETUP)
672 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_OVERLAP)
673 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_IN_PROCEEDING)
674 && !(e_ext.own_alerting && e_state == EPOINT_STATE_IN_ALERTING)
675 && !(e_ext.own_cause && e_state == EPOINT_STATE_IN_DISCONNECT)
676 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_SETUP)
677 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_OVERLAP)
678 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_OUT_PROCEEDING)
679 && !(e_ext.own_alerting && e_state == EPOINT_STATE_OUT_ALERTING)
680 && !(e_ext.own_cause && e_state == EPOINT_STATE_OUT_DISCONNECT)
681 && tone[0] && !!strncmp(tone,"crypt_*",6))
683 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) tone not provided since patterns are available\n", ea_endpoint->ep_serial);
689 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_TONE);
690 SCPY(message->param.tone.dir, e_ext.tones_dir[0]?e_ext.tones_dir:options.tones_dir);
691 SCPY(message->param.tone.name, tone);
692 message_put(message);
699 * hunts an mISDNport that is available for an outgoing call
700 * if no ifname was given, any interface that is not an extension
703 static struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel)
705 struct interface *interface;
706 struct mISDNport *mISDNport;
708 interface = interface_first;
710 /* first find the given interface or, if not given, one with no extension */
715 /* check for given interface */
718 if (!strcasecmp(interface->name, ifname))
720 /* found explicit interface */
721 printlog("%3d interface %s found as given\n", ea_endpoint->ep_serial, ifname);
727 if (!interface->extension)
729 /* found non extension */
730 printlog("%3d interface %s found, that is not an extension\n", ea_endpoint->ep_serial, interface->name);
735 interface = interface->next;
738 /* see if interface has ports */
739 if (!interface->ifport)
742 printlog("%3d interface %s has no active ports, skipping.\n", ea_endpoint->ep_serial, interface->name);
743 interface = interface->next;
747 /* select port by algorithm */
748 ifport_start = interface->port;
750 if (interface->hunt == HUNT_ROUNDROBIN)
752 while(ifport_start->next && index<interface->hunt_next)
754 ifport_start = ifport_start->next;
757 printlog("%3d starting with port#%d position %d (round-robin)\n", ea_endpoint->ep_serial, ifport_start->portnum, index);
761 ifport = ifport_start;
764 /* see if port is available */
765 if (!ifport->mISDNport)
767 printlog("%3d port#%d position %d is not available, skipping.\n", ea_endpoint->ep_serial, ifport->portnum, index);
770 mISDNport = ifport->mISDNport;
772 #warning admin block auch bei incomming calls
773 #warning calls releasen, wenn port entfernt wird, geblockt wird
774 /* see if port is administratively blocked */
777 printlog("%3d port#%d position %d is administratively blocked, skipping.\n", ea_endpoint->ep_serial, ifport->portnum, index);
781 /* see if link is up */
782 if (mISDNport->ptp && !mISDNport->l2link)
784 printlog("%3d port#%d position %d is ptp but layer 2 is down.\n", ea_endpoint->ep_serial, ifport->portnum, index);
785 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) skipping because it is PTP with L2 down\n", ea_endpoint->ep_serial);
789 /* check for channel form selection list */
791 selchannel = ifport->selchannel;
794 switch(selchannel->channel)
796 case CHANNEL_FREE: /* free channel */
797 if (mISDNport->b_inuse >= mISDNport->b_num)
798 break; /* all channel in use or reserverd */
801 while(i < mISDNport->b_num)
803 if (mISDNport->b_port[i] == NULL)
805 *channel = i+1+(i>=15);
806 printlog("%3d port#%d position %d selecting free channel %d\n", ea_endpoint->ep_serial, ifport->portnum, index, *channel);
813 case CHANNEL_ANY: /* don't ask for channel */
814 if (mISDNport->b_inuse >= mISDNport->b_num)
816 break; /* all channel in use or reserverd */
818 printlog("%3d port#%d position %d using with 'any channel'\n", ea_endpoint->ep_serial, ifport->portnum, index);
819 *channel = SEL_CHANNEL_ANY;
822 case CHANNEL_NO: /* call waiting */
823 printlog("%3d port#%d position %d using with 'no channel'\n", ea_endpoint->ep_serial, ifport->portnum, index);
824 *channel = SEL_CHANNEL_NO;
828 if (selchannel->channel<1 || selchannel->channel==16)
829 break; /* invalid channels */
830 i = selchannel->channel-1-(selchannel->channel>=17);
831 if (i >= mISDNport->b_num)
832 break; /* channel not in port */
833 if (mISDNport->b_port[i] == NULL)
835 *channel = selchannel->channel;
836 printlog("%3d port#%d position %d selecting given channel %d\n", ea_endpoint->ep_serial, ifport->portnum, index, *channel);
842 break; /* found channel */
843 selchannel = selchannel->next;
846 /* if channel was found, return mISDNport and channel */
849 /* setting next port to start next time */
850 if (interface->hunt == HUNT_ROUNDROBIN)
855 interface->hunt_next = index;
861 printlog("%3d port#%d position %d skipping, because no channel found.\n", ea_endpoint->ep_serial, ifport->portnum, index);
864 /* go next port, until all ports are checked */
866 ifport = ifport->next;
870 ifport = interface->ifport;
872 if (ifport != ifport_start)
875 return(NULL); /* no port found */
878 /* outgoing setup to port(s)
879 * ports will be created and a setup is sent if everything is ok. otherwhise
880 * the endpoint is destroyed.
882 void EndpointAppPBX::out_setup(void)
884 struct dialing_info dialinginfo;
886 // class pdss1 *pdss1;
887 struct port_list *portlist;
888 struct message *message;
890 int cause = CAUSE_RESSOURCEUNAVAIL;
893 struct mISDNport *mISDNport;
896 class EndpointAppPBX *atemp;
897 // char allowed_ports[256];
901 char ifname[sizeof(e_ext.interfaces)],
903 struct port_settings port_settings;
906 /* create settings for creating port */
907 memset(&port_settings, 0, sizeof(port_settings));
909 SCPY(port_settings.tones_dir, e_ext.tones_dir);
911 SCPY(port_settings.tones_dir, options.tones_dir);
912 port_settings.tout_setup = e_ext.tout_setup;
913 port_settings.tout_dialing = e_ext.tout_dialing;
914 port_settings.tout_proceeding = e_ext.tout_proceeding;
915 port_settings.tout_alerting = e_ext.tout_alerting;
916 port_settings.tout_disconnect = e_ext.tout_disconnect;
917 // port_settings.tout_hold = e_ext.tout_hold;
918 // port_settings.tout_park = e_ext.tout_park;
919 port_settings.no_seconds = e_ext.no_seconds;
921 /* 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 */
923 /* check what dialinginfo.itype we got */
924 switch(e_dialinginfo.itype)
926 /* *********************** call to extension or vbox */
927 case INFO_ITYPE_ISDN_EXTENSION:
928 /* check if we deny incoming calls when we use an extension */
929 if (e_ext.noknocking)
931 atemp = apppbx_first;
935 if (!strcmp(atemp->e_ext.number, e_ext.number))
941 PERROR("EPOINT(%d) noknocking and currently a call\n", ea_endpoint->ep_serial);
942 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYSPE_ call, port */
943 return; /* must exit here */
946 /* FALL THROUGH !!!! */
947 case INFO_ITYPE_VBOX:
948 /* get dialed extension's info */
949 // SCPY(exten, e_dialinginfo.number);
950 // if (strchr(exten, ','))
951 // *strchr(exten, ',') = '\0';
952 // if (!read_extension(&e_ext, exten))
953 if (!read_extension(&e_ext, e_dialinginfo.number))
955 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) extension %s not configured\n", ea_endpoint->ep_serial, e_dialinginfo.number);
956 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
957 return; /* must exit here */
960 if (e_dialinginfo.itype == INFO_ITYPE_VBOX)
962 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing directly to VBOX\n", ea_endpoint->ep_serial);
967 /* string from unconditional call forward (cfu) */
971 /* present to forwarded party */
972 if (e_ext.anon_ignore && e_callerinfo.id[0])
974 e_callerinfo.present = INFO_PRESENT_ALLOWED;
976 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
980 /* string from busy call forward (cfb) */
984 class EndpointAppPBX *checkapp = apppbx_first;
987 if (checkapp != this) /* any other endpoint except our own */
989 if (!strcmp(checkapp->e_ext.number, e_ext.number))
991 /* present to forwarded party */
992 if (e_ext.anon_ignore && e_callerinfo.id[0])
994 e_callerinfo.present = INFO_PRESENT_ALLOWED;
996 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
1000 checkapp = checkapp->next;
1004 /* string from no-response call forward (cfnr) */
1008 /* when cfnr is done, out_setup() will setup the call */
1011 /* present to forwarded party */
1012 if (e_ext.anon_ignore && e_callerinfo.id[0])
1014 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1018 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
1020 e_cfnr_release = now + e_ext.cfnr_delay;
1021 e_cfnr_call = now + e_ext.cfnr_delay + 1; /* call one second after release */
1022 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);
1026 /* call to all internal interfaces */
1027 p = e_ext.interfaces;
1028 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) generating multiple calls for extension %s to interfaces %s\n", ea_endpoint->ep_serial, e_dialinginfo.number, p);
1032 while(*p!=',' && *p!='\0')
1034 SCCAT(ifname, *p++);
1037 /* found interface */
1038 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
1039 /* hunt for mISDNport and create Port */
1040 mISDNport = hunt_port(ifname, &channel);
1043 printlog("%3d endpoint INTERFACE '%s' not found or busy\n", ea_endpoint->ep_serial, ifname);
1044 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) given interface: '%s' not found or too busy to accept calls.\n", ea_endpoint->ep_serial, e_ext.interfaces);
1047 /* creating INTERNAL port */
1048 SPRINT(portname, "%s-%d-out", mISDNport->interface_name, mISDNport->portnum);
1049 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport.channel_force);
1052 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port '%s' failed to create\n", ea_endpoint->ep_serial, mISDNport->interface_name);
1053 goto check_anycall_intern;
1055 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
1056 memset(&dialinginfo, 0, sizeof(dialinginfo));
1057 SCPY(dialinginfo.number, e_dialinginfo.number);
1058 dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
1059 dialinginfo.ntype = e_dialinginfo.ntype;
1060 /* create port_list relation */
1061 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->is_earlyb);
1064 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1066 goto check_anycall_intern;
1068 /* directory.list */
1069 if (e_callerinfo.id[0] && (e_ext.centrex || e_ext.display_name))
1071 dirname = parse_directory(e_callerinfo.id, e_callerinfo.ntype);
1073 SCPY(e_callerinfo.name, dirname);
1075 // dss1 = (class Pdss1 *)port;
1077 //printf("INTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.number);
1078 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1079 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1080 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1081 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1082 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1083 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1084 //terminal if (e_dialinginfo.number)
1085 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.number);
1086 /* handle restricted caller ids */
1087 apply_callerid_restriction(e_ext.anon_ignore, port->p_type, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.voip, message->param.setup.callerinfo.intern, message->param.setup.callerinfo.name);
1088 apply_callerid_restriction(e_ext.anon_ignore, port->p_type, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, NULL, message->param.setup.redirinfo.voip, message->param.setup.redirinfo.intern, 0);
1089 /* display callerid if desired for extension */
1090 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.voip, message->param.setup.callerinfo.intern, message->param.setup.callerinfo.name));
1091 //printf("\n\ndisplay = %s\n\n\n",message->param.setup.callerinfo.display);
1092 /* use cnip, if enabld */
1094 message->param.setup.callerinfo.name[0] = '\0';
1095 /* screen clip if prefix is required */
1096 if (message->param.setup.callerinfo.id[0] && e_ext.clip_prefix[0])
1098 SCPY(message->param.setup.callerinfo.id, e_ext.clip_prefix);
1099 SCAT(message->param.setup.callerinfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype));
1100 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1102 /* use internal caller id */
1103 if (e_callerinfo.intern[0] && (message->param.setup.callerinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
1105 SCPY(message->param.setup.callerinfo.id, e_callerinfo.intern);
1106 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1108 message_put(message);
1109 logmessage(message);
1113 /* string from parallel call forward (cfp) */
1117 if (e_ext.anon_ignore && e_callerinfo.id[0])
1119 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1123 vbox_only: /* entry point for answering machine only */
1124 cfu_only: /* entry point for cfu */
1125 cfb_only: /* entry point for cfb */
1126 cfnr_only: /* entry point for cfnr */
1127 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call extension %s for external destiantion(s) '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.number, p);
1131 /* only if vbox should be dialed, and terminal is given */
1133 if (!strcmp(p, "vbox") && e_ext.number[0])
1135 /* go to the end of p */
1138 /* answering vbox call */
1139 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) answering machine\n", ea_endpoint->ep_serial);
1141 if (!(port = new VBoxPort(PORT_TYPE_VBOX_OUT, &port_settings)))
1143 PERROR("EPOINT(%d) no mem for port\n", ea_endpoint->ep_serial);
1146 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocated port %s\n", ea_endpoint->ep_serial, port->p_name);
1147 UCPY(cfp, e_ext.number); /* cfp or any other direct forward/vbox */
1151 while(*p!=',' && *p!='\0')
1157 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cfp external %s\n", ea_endpoint->ep_serial, cfp);
1158 /* hunt for mISDNport and create Port */
1159 mISDNport = mISDNport_first;
1163 /* check for external or given interface */
1164 if (((!e_dialinginfo.interfaces[0])&&mISDNport->iftype==IF_EXTERN) || !strcmp(mISDNport->interface_name, e_dialinginfo.interfaces))
1166 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) interface '%s' found\n", ea_endpoint->ep_serial, mISDNport->interface_name);
1167 cause = CAUSE_NOCHANNEL; /* when failing: out of channels */
1168 /* if PTP, skip all down links */
1169 if (mISDNport->ptp && !mISDNport->l2link)
1171 printlog("%3d endpoint INTERFACE Layer 2 of interface '%s' is down.\n", ea_endpoint->ep_serial, mISDNport->interface_name);
1172 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) skipping because it is PTP with L2 down\n", ea_endpoint->ep_serial);
1173 mISDNport = mISDNport->next;
1176 /* if no channel is available */
1177 if (mISDNport->multilink || !mISDNport->ntmode || mISDNport->ptp)
1181 ii = mISDNport->b_num;
1184 if (mISDNport->b_state[i])
1188 if (use >= mISDNport->b_num)
1190 printlog("%3d endpoint INTERFACE Interface '%s' has no free channel.\n", ea_endpoint->ep_serial, mISDNport->interface_name);
1191 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) skipping because it is not single link port_list NT-modem OR no channel available.\n", ea_endpoint->ep_serial);
1192 mISDNport = mISDNport->next;
1196 /* found interface */
1197 printlog("%3d endpoint INTERFACE Interface '%s' found for external call.\n", ea_endpoint->ep_serial, mISDNport->interface_name);
1200 mISDNport = mISDNport->next;
1204 /* creating EXTERNAL port*/
1205 SPRINT(portname, "%s-%d-out", mISDNport->interface_name, mISDNport->portnum);
1206 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings);
1207 earlyb = mISDNport->is_earlyb;
1211 printlog("%3d endpoint INTERFACE External interface not found or busy.\n", ea_endpoint->ep_serial);
1212 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) given interface: '%s' too busy to accept calls.\n", ea_endpoint->ep_serial, e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1217 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port found or created, which is idle.\n", ea_endpoint->ep_serial);
1218 goto check_anycall_intern;
1220 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found or created port %s\n", ea_endpoint->ep_serial, port->p_name);
1221 memset(&dialinginfo, 0, sizeof(dialinginfo));
1222 SCPY(dialinginfo.number, cfp);
1223 dialinginfo.itype = INFO_ITYPE_EXTERN;
1224 dialinginfo.ntype = e_dialinginfo.ntype;
1225 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
1228 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1230 goto check_anycall_intern;
1232 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.number);
1233 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1234 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1235 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1236 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1237 /* if clip is hidden */
1238 if (e_ext.clip==CLIP_HIDE && port->p_type!=PORT_TYPE_VBOX_OUT)
1240 SCPY(message->param.setup.callerinfo.id, e_ext.callerid);
1241 SCPY(message->param.setup.callerinfo.intern, e_ext.number);
1242 message->param.setup.callerinfo.ntype = e_ext.callerid_type;
1243 message->param.setup.callerinfo.present = e_ext.callerid_present;
1245 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1246 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1247 //terminal if (e_dialinginfo.number)
1248 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.number);
1249 /* handle restricted caller ids */
1250 apply_callerid_restriction(e_ext.anon_ignore, port->p_type, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.voip, message->param.setup.callerinfo.intern, message->param.setup.callerinfo.name);
1251 apply_callerid_restriction(e_ext.anon_ignore, port->p_type, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, NULL, message->param.setup.redirinfo.voip, message->param.setup.redirinfo.intern, 0);
1252 /* display callerid if desired for extension */
1253 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.voip, message->param.setup.callerinfo.intern, message->param.setup.callerinfo.name));
1254 message_put(message);
1255 logmessage(message);
1259 check_anycall_intern:
1260 /* now we have all ports created */
1263 printlog("%3d endpoint INTERFACE No port or no parallel forwarding defined. Nothing to call to.\n", ea_endpoint->ep_serial);
1264 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port or no cfp defined for extension, nothing to dial.\n", ea_endpoint->ep_serial);
1265 if (!ea_endpoint->ep_call_id)
1267 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
1268 return; /* must exit here */
1272 /* *********************** external call */
1274 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.number);
1275 /* call to extenal interfaces */
1276 p = e_dialinginfo.number;
1280 while(*p!=',' && *p!='\0')
1281 SCCAT(number, *p++);
1285 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");
1286 /* hunt for mISDNport and create Port */
1287 mISDNport = mISDNport_first;
1291 /* check for external or given interface */
1292 if ((!e_dialinginfo.interfaces[0]&&mISDNport->iftype==IF_EXTERN) || !strcmp(mISDNport->interface_name, e_dialinginfo.interfaces))
1294 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) interface '%s' found\n", ea_endpoint->ep_serial, mISDNport->interface_name);
1295 cause = CAUSE_NOCHANNEL; /* when failing: out of channels */
1296 /* if PTP, skip all down links */
1297 if (mISDNport->ptp && !mISDNport->l2link)
1299 printlog("%3d endpoint INTERFACE Layer 2 of interface '%s' is down.\n", ea_endpoint->ep_serial, mISDNport->interface_name);
1300 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) skipping because it is PTP with L2 down\n", ea_endpoint->ep_serial);
1301 mISDNport = mISDNport->next;
1304 /* if no channel is available */
1305 if (mISDNport->multilink || !mISDNport->ntmode || mISDNport->ptp)
1309 ii = mISDNport->b_num;
1312 if (mISDNport->b_state[i])
1316 if (use >= mISDNport->b_num)
1318 printlog("%3d endpoint INTERFACE Interface '%s' has no free channel.\n", ea_endpoint->ep_serial, mISDNport->interface_name);
1319 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) skipping because it is not single link port_list NT-modem OR no channel available.\n", ea_endpoint->ep_serial);
1320 mISDNport = mISDNport->next;
1324 /* found interface */
1325 printlog("%3d endpoint INTERFACE Interface '%s' found for external call.\n", ea_endpoint->ep_serial, mISDNport->interface_name);
1328 mISDNport = mISDNport->next;
1332 printlog("%3d endpoint INTERFACE External interface not found or busy.\n", ea_endpoint->ep_serial);
1333 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) given interface: '%s' too busy to accept calls.\n", ea_endpoint->ep_serial, e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1334 goto check_anycall_extern;
1336 /* creating EXTERNAL port*/
1337 SPRINT(portname, "%s-%d-out", mISDNport->interface_name, mISDNport->portnum);
1338 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings);
1341 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no external port available\n", ea_endpoint->ep_serial);
1342 goto check_anycall_extern;
1344 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
1345 memset(&dialinginfo, 0, sizeof(dialinginfo));
1346 SCPY(dialinginfo.number, number);
1347 dialinginfo.itype = INFO_ITYPE_EXTERN;
1348 dialinginfo.ntype = e_dialinginfo.ntype;
1349 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->is_earlyb);
1352 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1354 goto check_anycall_extern;
1356 // dss1 = (class Pdss1 *)port;
1357 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.number);
1358 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1359 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1360 SCPY(message->param.setup.dialinginfo.number, number);
1361 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1362 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1363 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1364 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1365 //terminal if (e_dialinginfo.number)
1366 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.number);
1367 /* handle restricted caller ids */
1368 apply_callerid_restriction(e_ext.anon_ignore, port->p_type, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.voip, message->param.setup.callerinfo.intern, message->param.setup.callerinfo.name);
1369 apply_callerid_restriction(e_ext.anon_ignore, port->p_type, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, NULL, message->param.setup.redirinfo.voip, message->param.setup.redirinfo.intern, 0);
1370 /* display callerid if desired for extension */
1371 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.voip, message->param.setup.callerinfo.intern, message->param.setup.callerinfo.name));
1372 message_put(message);
1373 logmessage(message);
1377 check_anycall_extern:
1378 /* now we have all ports created */
1381 printlog("%3d endpoint INTERFACE No free port found for making any call.\n", ea_endpoint->ep_serial);
1382 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port found which is idle for at least one number\n", ea_endpoint->ep_serial);
1383 if (!ea_endpoint->ep_call_id)
1385 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
1386 return; /* must exit here */
1394 /* handler for endpoint
1398 int EndpointAppPBX::handler(void)
1400 if (e_crypt_state!=CM_ST_NULL)
1405 /* process answering machine (play) handling */
1408 if (e_action->index == ACTION_VBOX_PLAY)
1411 /* process action timeout */
1412 if (e_action_timeout)
1413 if (now_d >= e_action_timeout)
1415 if (e_state!=EPOINT_STATE_CONNECT)
1418 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current action timed out.\n", ea_endpoint->ep_serial);
1419 e_multipoint_cause = CAUSE_NOUSER;
1420 e_multipoint_location = LOCATION_PRIVATE_LOCAL;
1421 new_state(EPOINT_STATE_IN_OVERLAP);
1424 return(1); /* we must exit, because our endpoint might be gone */
1426 e_action_timeout = 0;
1429 /* process action timeout */
1430 if (e_match_timeout)
1431 if (now_d >= e_match_timeout)
1434 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we got a match timeout.\n", ea_endpoint->ep_serial);
1436 return(1); /* we must exit, because our endpoint might be gone */
1441 /* process redialing (epoint redials to port) */
1444 if (now_d >= e_redial)
1447 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial.\n", ea_endpoint->ep_serial);
1449 new_state(EPOINT_STATE_OUT_SETUP);
1450 /* call special setup routine */
1457 /* process powerdialing (epoint redials to epoint) */
1458 if (e_powerdialing > 0)
1460 if (now_d >= e_powerdialing)
1462 e_powerdialing = -1; /* leave power dialing on */
1463 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial of powerdial.\n", ea_endpoint->ep_serial);
1466 e_ruleset = ruleset_main;
1468 e_rule = e_ruleset->rule_first;
1470 new_state(EPOINT_STATE_IN_OVERLAP);
1476 /* process call forward no response */
1479 struct port_list *portlist;
1480 struct message *message;
1482 if (now >= e_cfnr_release)
1484 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-no-response time has expired, hanging up.\n", ea_endpoint->ep_serial);
1487 /* release all ports */
1488 while((portlist = ea_endpoint->ep_portlist))
1490 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1491 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
1492 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1493 message_put(message);
1494 logmessage(message);
1495 ea_endpoint->free_portlist(portlist);
1498 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
1499 message->param.channel = CHANNEL_STATE_HOLD;
1500 message_put(message);
1501 /* indicate no patterns */
1502 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_NOPATTERN);
1503 message_put(message);
1504 /* set setup state, since we have no response from the new call */
1505 new_state(EPOINT_STATE_OUT_SETUP);
1510 if (now >= e_cfnr_call)
1512 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-busy time has expired, calling the forwarded number: %s.\n", ea_endpoint->ep_serial, e_ext.cfnr);
1518 /* handle connection to user */
1519 if (e_state == EPOINT_STATE_IDLE)
1521 /* epoint is idle, check callback */
1523 if (now_d >= e_callback)
1525 e_callback = 0; /* done with callback */
1526 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting callback.\n", ea_endpoint->ep_serial);
1527 new_state(EPOINT_STATE_OUT_SETUP);
1533 /* check for password timeout */
1535 if (e_action->index==ACTION_PASSWORD || e_action->index==ACTION_PASSWORD_WRITE)
1537 struct port_list *portlist;
1539 if (now >= e_password_timeout)
1541 e_ruleset = ruleset_main;
1543 e_rule = e_ruleset->rule_first;
1545 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) password timeout %s\n", ea_endpoint->ep_serial, e_extdialing);
1546 printlog("%3d endpoint PASSWORD timeout\n", ea_endpoint->ep_serial);
1547 e_connectedmode = 0;
1549 new_state(EPOINT_STATE_OUT_DISCONNECT);
1550 portlist = ea_endpoint->ep_portlist;
1553 message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
1554 set_tone(portlist, "cause_10");
1564 /* doing a hookflash */
1565 void EndpointAppPBX::hookflash(void)
1569 /* be sure that we are active */
1571 e_tx_state = NOTIFY_STATE_ACTIVE;
1573 printlog("%3d endpoint HOOKFLASH\n", ea_endpoint->ep_serial);
1574 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf hookflash detected.\n", ea_endpoint->ep_serial);
1575 if (ea_endpoint->ep_use > 1)
1577 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot hooflash while child process is running.\n", ea_endpoint->ep_serial);
1580 /* dialtone after pressing the hash key */
1581 process_hangup(e_call_cause, e_call_location);
1582 e_multipoint_cause = CAUSE_NOUSER;
1583 e_multipoint_location = LOCATION_PRIVATE_LOCAL;
1584 port = find_port_id(ea_endpoint->ep_portlist->port_id);
1587 port->set_echotest(0);
1589 if (ea_endpoint->ep_call_id)
1591 release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
1593 e_ruleset = ruleset_main;
1595 e_rule = e_ruleset->rule_first;
1597 new_state(EPOINT_STATE_IN_OVERLAP);
1598 e_connectedmode = 1;
1599 SCPY(e_dialinginfo.number, e_ext.prefix);
1600 e_extdialing = e_dialinginfo.number;
1602 if (e_dialinginfo.number[0])
1604 set_tone(ea_endpoint->ep_portlist, "dialing");
1608 set_tone(ea_endpoint->ep_portlist, "dialpbx");
1615 /* messages from port
1617 /* port MESSAGE_SETUP */
1618 void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, union parameter *param)
1620 struct message *message;
1623 char extension1[32];
1625 int writeext; /* flags need to write extension after modification */
1628 portlist->port_type = param->setup.port_type;
1629 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
1630 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
1631 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
1632 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
1633 e_dtmf = param->setup.dtmf;
1635 /* screen by interface */
1636 if (e_callerinfo.interface[0])
1638 /* screen incoming caller id */
1639 screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present);
1641 colp, outclip, outcolp
1643 /* process extension */
1644 if (e_callerinfo.itype == INFO_ITYPE_INTERN)
1646 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is extension\n", ea_endpoint->ep_serial);
1647 /* port makes call from extension */
1648 SCPY(e_callerinfo.intern, e_callerinfo.id);
1649 SCPY(e_ext.number, e_callerinfo.intern);
1650 SCPY(e_extension_interface, e_callerinfo.interface);
1653 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is external or voip\n", ea_endpoint->ep_serial);
1655 printlog("%3d incoming %s='%s'%s%s%s%s dialing='%s'\n",
1656 ea_endpoint->ep_serial,
1657 (e_callerinfo.intern[0])?"SETUP from extension":"SETUP from extern",
1658 (e_callerinfo.intern[0])?e_callerinfo.intern:e_callerinfo.id,
1659 (e_callerinfo.present==INFO_PRESENT_RESTRICTED)?" anonymous":"",
1660 (e_redirinfo.id[0])?"redirected='":"",
1662 (e_redirinfo.id[0])?"'":"",
1663 e_dialinginfo.number
1666 if (e_callerinfo.itype == INFO_ITYPE_INTERN)
1668 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1670 /* get extension's info about caller */
1671 if (!read_extension(&e_ext, e_ext.number))
1673 /* extension doesn't exist */
1674 printlog("%3d endpoint EXTENSION '%s' doesn't exist, please check or create.\n", ea_endpoint->ep_serial, e_callerinfo.id);
1675 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting call from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1676 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
1677 new_state(EPOINT_STATE_OUT_DISCONNECT);
1678 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
1679 e_ext.number[0] = '\0'; /* no terminal */
1684 /* put prefix (next) in front of e_dialinginfo.number */
1687 SPRINT(buffer, "%s%s", e_ext.next, e_dialinginfo.number);
1688 SCPY(e_dialinginfo.number, buffer);
1689 e_ext.next[0] = '\0';
1691 } else if (e_ext.prefix[0])
1693 SPRINT(buffer, "%s%s", e_ext.prefix, e_dialinginfo.number);
1694 SCPY(e_dialinginfo.number, buffer);
1697 /* screen caller id */
1698 e_callerinfo.screen = INFO_SCREEN_NETWORK;
1700 SCPY(e_callerinfo.name, e_ext.name);
1701 /* use caller id (or if exist: id_next_call) for this call */
1702 if (e_ext.id_next_call_present >= 0)
1704 SCPY(e_callerinfo.id, e_ext.id_next_call);
1705 /* if we restrict the pesentation */
1706 if (e_ext.id_next_call_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1707 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1708 else e_callerinfo.present = e_ext.id_next_call_present;
1709 e_callerinfo.ntype = e_ext.id_next_call_type;
1710 e_ext.id_next_call_present = -1;
1714 SCPY(e_callerinfo.id, e_ext.callerid);
1715 /* if we restrict the pesentation */
1716 if (e_ext.callerid_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1717 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1718 else e_callerinfo.present = e_ext.callerid_present;
1719 e_callerinfo.ntype = e_ext.callerid_type;
1722 /* extension is written */
1724 write_extension(&e_ext, e_ext.number);
1726 /* set volume of rx and tx */
1727 if (param->setup.callerinfo.itype == INFO_ITYPE_INTERN)
1728 if (e_ext.txvol!=256 || e_ext.rxvol!=256)
1730 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
1731 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
1732 message->param.mISDNsignal.rxvol = e_ext.txvol;
1733 message->param.mISDNsignal.txvol = e_ext.rxvol;
1734 message_put(message);
1737 /* start recording if enabled */
1738 if (e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO))
1740 /* check if we are a terminal */
1741 if (e_ext.number[0] == '\0')
1742 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
1745 port = find_port_id(portlist->port_id);
1747 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
1752 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from external port\n", ea_endpoint->ep_serial);
1753 /* no terminal identification */
1754 e_ext.number[0] = '\0';
1755 e_extension_interface[0] = '\0';
1756 memset(&e_ext, 0, sizeof(e_ext));
1757 e_ext.rights = 4; /* right to dial internat */
1761 e_ruleset = ruleset_main;
1763 e_rule = e_ruleset->rule_first;
1765 e_extdialing = e_dialinginfo.number;
1766 new_state(EPOINT_STATE_IN_SETUP);
1767 if (e_dialinginfo.number[0])
1769 set_tone(portlist, "dialing");
1772 if (e_ext.number[0])
1773 set_tone(portlist, "dialpbx");
1775 set_tone(portlist, "dialtone");
1778 if (e_state == EPOINT_STATE_IN_SETUP)
1780 /* request MORE info, if not already at higher state */
1781 new_state(EPOINT_STATE_IN_OVERLAP);
1782 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_OVERLAP);
1783 message_put(message);
1784 logmessage(message);
1788 /* port MESSAGE_INFORMATION */
1789 void EndpointAppPBX::port_information(struct port_list *portlist, int message_type, union parameter *param)
1791 printlog("%3d incoming INFORMATION information='%s'\n",
1792 ea_endpoint->ep_serial,
1793 param->information.number
1797 /* turn off dtmf detection, in case dtmf is sent with keypad information */
1800 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) received dialing information, so dtmf is now disabled, to prevent double detection by keypad+dtmf.\n", ea_endpoint->ep_serial, param->information.number, e_ext.number, e_callerinfo.id);
1804 /* if vbox_play is done, the information are just used as they come */
1806 if (e_action->index == ACTION_VBOX_PLAY)
1808 /* concat dialing string */
1809 SCAT(e_dialinginfo.number, param->information.number);
1814 /* keypad when disconnect but in connected mode */
1815 if (e_state==EPOINT_STATE_OUT_DISCONNECT && e_connectedmode)
1817 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received after disconnect: %s.\n", ea_endpoint->ep_serial, param->information.number);
1818 /* processing keypad function */
1819 if (param->information.number[0] == '0')
1826 /* keypad when connected */
1827 if (e_state == EPOINT_STATE_CONNECT && e_ext.keypad)
1829 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.number);
1830 /* processing keypad function */
1831 if (param->information.number[0] == '0')
1835 if (param->information.number[0])
1836 keypad_function(param->information.number[0]);
1839 if (e_state != EPOINT_STATE_IN_OVERLAP)
1841 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in overlap, or connect state.\n", ea_endpoint->ep_serial);
1844 if (!param->information.number[0])
1846 if (e_dialinginfo.number[0]=='\0' && !e_action)
1848 set_tone(portlist, "dialing");
1851 if (e_action->index==ACTION_OUTDIAL
1852 || e_action->index==ACTION_EXTERNAL)
1855 set_tone(portlist, "dialing");
1856 else if (!e_extdialing[0])
1857 set_tone(portlist, "dialing");
1859 /* concat dialing string */
1860 SCAT(e_dialinginfo.number, param->information.number);
1864 /* port MESSAGE_DTMF */
1865 void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
1867 printlog("%3d incoming DTMF digit='%c'\n",
1868 ea_endpoint->ep_serial,
1871 /* only if dtmf detection is enabled */
1874 PDEBUG(DEBUG_EPOINT, "dtmf detection is disabled\n");
1879 NOTE: vbox is now handled due to overlap state
1880 /* if vbox_play is done, the dtmf digits are just used as they come */
1882 if (e_action->index == ACTION_VBOX_PLAY)
1884 /* concat dialing string */
1885 if (strlen(e_dialinginfo.number)+1 < sizeof(e_dialinginfo.number))
1887 e_dialinginfo.number[strlen(e_dialinginfo.number)+1] = '\0';
1888 e_dialinginfo.number[strlen(e_dialinginfo.number)] = param->dtmf;
1891 /* continue to process *X# sequences */
1895 /* check for *X# sequence */
1896 if (e_state == EPOINT_STATE_CONNECT)
1898 if (e_dtmf_time+3 < now)
1900 /* the last digit was too far in the past to be a sequence */
1901 if (param->dtmf == '*')
1902 /* only start is allowed in the sequence */
1908 /* we have a sequence of digits, see what we got */
1909 if (param->dtmf == '*')
1911 else if (param->dtmf>='0' && param->dtmf<='9')
1913 /* we need to have a star before we receive the digit of the sequence */
1914 if (e_dtmf_last == '*')
1915 e_dtmf_last = param->dtmf;
1916 } else if (param->dtmf == '#')
1919 if (e_dtmf_last>='0' && e_dtmf_last<='9')
1921 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf sequence *%c# detected.\n", ea_endpoint->ep_serial, e_dtmf_last);
1922 if (e_dtmf_last == '0')
1927 /* processing keypad function */
1929 keypad_function(e_dtmf_last);
1935 /* set last time of dtmf */
1940 /* check for ## hookflash during dialing */
1942 if (e_action->index==ACTION_PASSWORD
1943 || e_action->index==ACTION_PASSWORD_WRITE)
1945 if (param->dtmf=='#') /* current digit is '#' */
1947 if (e_state==EPOINT_STATE_IN_DISCONNECT
1948 || (e_state!=EPOINT_STATE_CONNECT && e_dtmf_time+3>=now && e_dtmf_last=='#')) /* when disconnected, just #. when dialing, ##. */
1965 /* dialing using dtmf digit */
1966 if (e_state==EPOINT_STATE_IN_OVERLAP)// && e_state==e_connectedmode)
1968 if (e_dialinginfo.number[0]=='\0' && !e_action)
1970 set_tone(portlist, "dialing");
1972 /* concat dialing string */
1973 if (strlen(e_dialinginfo.number)+1 < sizeof(e_dialinginfo.number))
1975 e_dialinginfo.number[strlen(e_dialinginfo.number)+1] = '\0';
1976 e_dialinginfo.number[strlen(e_dialinginfo.number)] = param->dtmf;
1982 /* port MESSAGE_CRYPT */
1983 void EndpointAppPBX::port_crypt(struct port_list *portlist, int message_type, union parameter *param)
1985 /* send crypt response to cryptman */
1986 if (param->crypt.type == CR_MESSAGE_IND)
1987 cryptman_msg2man(param->crypt.data, param->crypt.len);
1989 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
1992 /* port MESSAGE_OVERLAP */
1993 void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, union parameter *param)
1995 struct message *message;
1997 /* signal to call tool */
1998 admin_call_response(e_adminid, ADMIN_CALL_SETUP_ACK, "", 0, 0, 0);
2000 printlog("%3d incoming SETUP ACKNOWLEDGE\n",
2001 ea_endpoint->ep_serial
2003 if (e_dialing_queue[0] && portlist)
2005 /* send what we have not dialed yet, because we had no setup complete */
2006 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing pending digits: '%s'\n", ea_endpoint->ep_serial, e_dialing_queue);
2007 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2008 SCPY(message->param.information.number, e_dialing_queue);
2009 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
2010 message_put(message);
2011 logmessage(message);
2012 e_dialing_queue[0] = '\0';
2014 /* check if pattern is available */
2015 if (!ea_endpoint->ep_portlist->next && portlist->earlyb) /* one port_list relation and tones available */
2017 /* indicate patterns */
2018 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_PATTERN);
2019 message_put(message);
2021 /* connect audio, if not already */
2022 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2023 message->param.channel = CHANNEL_STATE_CONNECT;
2024 message_put(message);
2027 /* indicate no patterns */
2028 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_NOPATTERN);
2029 message_put(message);
2031 /* disconnect audio, if not already */
2032 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2033 message->param.channel = CHANNEL_STATE_HOLD;
2034 message_put(message);
2036 new_state(EPOINT_STATE_OUT_OVERLAP);
2037 /* if we are in a call */
2038 if (ea_endpoint->ep_call_id)
2040 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
2041 memcpy(&message->param, param, sizeof(union parameter));
2042 message_put(message);
2046 /* port MESSAGE_PROCEEDING */
2047 void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_type, union parameter *param)
2049 struct message *message;
2051 /* signal to call tool */
2052 admin_call_response(e_adminid, ADMIN_CALL_PROCEEDING, "", 0, 0, 0);
2054 printlog("%3d incoming PROCEEDING\n",
2055 ea_endpoint->ep_serial
2057 e_state = EPOINT_STATE_OUT_PROCEEDING;
2058 /* check if pattern is availatle */
2059 if (!ea_endpoint->ep_portlist->next && (portlist->earlyb || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
2061 /* indicate patterns */
2062 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_PATTERN);
2063 message_put(message);
2065 /* connect audio, if not already */
2066 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2067 message->param.channel = CHANNEL_STATE_CONNECT;
2068 message_put(message);
2071 /* indicate no patterns */
2072 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_NOPATTERN);
2073 message_put(message);
2075 /* disconnect audio, if not already */
2076 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2077 message->param.channel = CHANNEL_STATE_HOLD;
2078 message_put(message);
2080 /* if we are in a call */
2081 if (ea_endpoint->ep_call_id)
2083 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
2084 memcpy(&message->param, param, sizeof(union parameter));
2085 message_put(message);
2089 /* port MESSAGE_ALERTING */
2090 void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type, union parameter *param)
2092 struct message *message;
2094 /* signal to call tool */
2095 admin_call_response(e_adminid, ADMIN_CALL_ALERTING, "", 0, 0, 0);
2097 printlog("%3d incoming ALERTING\n",
2098 ea_endpoint->ep_serial
2100 new_state(EPOINT_STATE_OUT_ALERTING);
2101 /* check if pattern is available */
2102 if (!ea_endpoint->ep_portlist->next && (portlist->earlyb || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
2104 /* indicate patterns */
2105 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_PATTERN);
2106 message_put(message);
2108 /* connect audio, if not already */
2109 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2110 message->param.channel = CHANNEL_STATE_CONNECT;
2111 message_put(message);
2114 /* indicate no patterns */
2115 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_NOPATTERN);
2116 message_put(message);
2118 /* disconnect audio, if not already */
2119 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2120 message->param.channel = CHANNEL_STATE_HOLD;
2121 message_put(message);
2123 /* if we are in a call */
2124 if (ea_endpoint->ep_call_id)
2126 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
2127 memcpy(&message->param, param, sizeof(union parameter));
2128 message_put(message);
2132 /* port MESSAGE_CONNECT */
2133 void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, union parameter *param)
2135 struct message *message;
2137 unsigned long port_id = portlist->port_id;
2138 struct port_list *tportlist;
2141 /* signal to call tool */
2142 admin_call_response(e_adminid, ADMIN_CALL_CONNECT, numberrize_callerinfo(param->connectinfo.id,param->connectinfo.ntype), 0, 0, 0);
2144 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_connectinfo));
2145 printlog("%3d incoming CONNECT id='%s'%s\n",
2146 ea_endpoint->ep_serial,
2147 (e_connectinfo.intern[0])?e_connectinfo.intern:e_connectinfo.id,
2148 (e_connectinfo.present==INFO_PRESENT_RESTRICTED)?" anonymous":""
2150 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (start)\n", ea_endpoint->ep_serial);
2151 while(ea_endpoint->ep_portlist->next) /* as long as we have at least two ports */
2153 tportlist = ea_endpoint->ep_portlist;
2154 if (tportlist->port_id == port_id) /* if the first portlist is the calling one, the second must be a different one */
2155 tportlist = tportlist->next;
2156 if (tportlist->port_id == port_id)
2158 PERROR("EPOINT(%d) software error: this should not happen since the portlist list must not have two links to the same port - exitting.\n");
2161 message = message_create(ea_endpoint->ep_serial, tportlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2162 message->param.disconnectinfo.cause = 26; /* non selected user clearing */
2163 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2164 message_put(message);
2165 logmessage(message);
2166 ea_endpoint->free_portlist(tportlist);
2168 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (end)\n", ea_endpoint->ep_serial);
2172 /* screen by interface */
2173 if (e_callerinfo.interface[0])
2175 /* screen incoming caller id */
2176 screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present);
2179 /* screen connected name */
2181 SCPY(e_connectinfo.name, e_ext.name);
2183 /* add internal id to colp */
2184 SCPY(e_connectinfo.intern, e_ext.number);
2186 /* we store the connected port number */
2187 SCPY(e_extension_interface, e_connectinfo.interfaces);
2189 /* for internal and am calls, we get the extension's id */
2190 if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE)
2192 SCPY(e_connectinfo.id, e_ext.callerid);
2193 SCPY(e_connectinfo.intern, e_ext.number);
2194 e_connectinfo.itype = INFO_ITYPE_INTERN;
2195 e_connectinfo.ntype = e_ext.callerid_type;
2196 e_connectinfo.present = e_ext.callerid_present;
2198 if (portlist->port_type==PORT_TYPE_VBOX_OUT)
2200 e_connectinfo.itype = INFO_ITYPE_VBOX;
2201 e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2204 new_state(EPOINT_STATE_CONNECT);
2206 /* set volume of rx and tx */
2207 if (e_ext.txvol!=256 || e_ext.rxvol!=256)
2209 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2210 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2211 message->param.mISDNsignal.rxvol = e_ext.txvol;
2212 message->param.mISDNsignal.txvol = e_ext.rxvol;
2213 message_put(message);
2216 e_cfnr_call = e_cfnr_release = 0;
2217 if (e_ext.number[0])
2218 e_dtmf = 1; /* allow dtmf */
2219 // if (call_countrelations(ea_endpoint->ep_call_id) == 2)
2222 /* other calls with no caller id (or not available for the extension) and force colp */
2223 if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE)
2225 e_connectinfo.present = INFO_PRESENT_NOTAVAIL;
2226 if (portlist->port_type==PORT_TYPE_DSS1_TE_OUT || portlist->port_type==PORT_TYPE_DSS1_NT_OUT) /* external extension answered */
2228 port = find_port_id(portlist->port_id);
2231 SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.number, &e_connectinfo.ntype));
2232 e_connectinfo.present = INFO_PRESENT_ALLOWED;
2236 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
2237 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
2238 message_put(message);
2240 if (ea_endpoint->ep_call_id)
2242 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2243 message->param.channel = CHANNEL_STATE_CONNECT;
2244 message_put(message);
2245 } else if (!e_adminid)
2248 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have a callback, so we create a call with cbcaller: \"%s\".\n", ea_endpoint->ep_serial, e_cbcaller);
2249 SCPY(e_ext.number, e_cbcaller);
2250 new_state(EPOINT_STATE_IN_OVERLAP);
2251 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) callback from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2253 /* get extension's info about terminal */
2254 if (!read_extension(&e_ext, e_ext.number))
2256 /* extension doesn't exist */
2257 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2258 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
2259 new_state(EPOINT_STATE_OUT_DISCONNECT);
2260 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
2264 /* put prefix in front of e_cbdialing */
2265 SPRINT(buffer, "%s%s", e_ext.prefix, e_cbdialing);
2266 SCPY(e_dialinginfo.number, buffer);
2267 e_dialinginfo.itype = INFO_ITYPE_EXTERN;
2268 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
2270 /* use caller id (or if exist: id_next_call) for this call */
2271 e_callerinfo.screen = INFO_SCREEN_NETWORK;
2272 SCPY(e_callerinfo.intern, e_ext.number);
2273 if (e_ext.id_next_call_present >= 0)
2275 SCPY(e_callerinfo.id, e_ext.id_next_call);
2276 e_callerinfo.present = e_ext.id_next_call_present;
2277 e_callerinfo.ntype = e_ext.id_next_call_type;
2278 e_ext.id_next_call_present = -1;
2279 /* extension is written */
2280 write_extension(&e_ext, e_ext.number);
2283 SCPY(e_callerinfo.id, e_ext.callerid);
2284 e_callerinfo.present = e_ext.callerid_present;
2285 e_callerinfo.ntype = e_ext.callerid_type;
2288 e_connectedmode = 1; /* dtmf-hangup & disconnect prevention */
2291 /* check if caller id is NOT authenticated */
2292 if (!parse_callbackauth(e_ext.number, &e_callbackinfo))
2294 /* make call state to enter password */
2295 new_state(EPOINT_STATE_IN_OVERLAP);
2296 e_action = &action_password_write;
2297 e_match_timeout = 0;
2298 e_match_to_action = NULL;
2299 e_dialinginfo.number[0] = '\0';
2300 e_extdialing = strchr(e_dialinginfo.number, '\0');
2301 e_password_timeout = now+20;
2305 /* incoming call (callback) */
2306 e_ruleset = ruleset_main;
2308 e_rule = e_ruleset->rule_first;
2310 e_extdialing = e_dialinginfo.number;
2311 if (e_dialinginfo.number[0])
2313 set_tone(portlist, "dialing");
2317 set_tone(portlist, "dialpbx");
2320 } else /* testcall */
2322 set_tone(portlist, "hold");
2325 /* start recording if enabled, not when answering machine answers */
2326 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))
2328 /* check if we are a terminal */
2329 if (e_ext.number[0] == '\0')
2330 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
2333 port = find_port_id(portlist->port_id);
2335 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
2340 /* port MESSAGE_DISCONNECT MESSAGE_RELEASE */
2341 void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
2343 struct message *message;
2345 unsigned long port_id = portlist->port_id;
2349 /* signal to call tool */
2350 admin_call_response(e_adminid, (message_type==MESSAGE_DISCONNECT)?ADMIN_CALL_DISCONNECT:ADMIN_CALL_RELEASE, "", param->disconnectinfo.cause, param->disconnectinfo.location, 0);
2352 printlog("%3d incoming %s cause='%d' (%s) location='%d' (%s)\n",
2353 ea_endpoint->ep_serial,
2354 (message_type==MESSAGE_DISCONNECT)?"DISCONNECT":"RELEASE",
2355 param->disconnectinfo.cause,
2356 (param->disconnectinfo.cause>0 && param->disconnectinfo.cause<128)?isdn_cause[param->disconnectinfo.cause].english:"-",
2357 param->disconnectinfo.location,
2358 (param->disconnectinfo.location>=0 && param->disconnectinfo.location<16)?isdn_location[param->disconnectinfo.location].english:"-"
2361 //#warning does this work? only disconnect when incoming port hat not already disconnected yet?
2362 if (e_state==EPOINT_STATE_IN_DISCONNECT && message_type!=MESSAGE_RELEASE)// || e_state==EPOINT_STATE_OUT_DISCONNECT || e_state==EPOINT_STATE_IDLE)
2364 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are already disconnected.\n", ea_endpoint->ep_serial);
2369 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);
2370 if (param->disconnectinfo.cause == CAUSE_REJECTED) /* call rejected */
2372 e_multipoint_cause = CAUSE_REJECTED;
2373 e_multipoint_location = param->disconnectinfo.location;
2375 if (param->disconnectinfo.cause==CAUSE_NORMAL && e_multipoint_cause!=CAUSE_REJECTED) /* reject via hangup */
2377 e_multipoint_cause = CAUSE_NORMAL;
2378 e_multipoint_location = param->disconnectinfo.location;
2380 if (param->disconnectinfo.cause==CAUSE_BUSY && e_multipoint_cause!=CAUSE_REJECTED && e_multipoint_cause!=CAUSE_NORMAL) /* busy */
2382 e_multipoint_cause = CAUSE_BUSY;
2383 e_multipoint_location = param->disconnectinfo.location;
2385 if (param->disconnectinfo.cause==CAUSE_OUTOFORDER && e_multipoint_cause!=CAUSE_BUSY && e_multipoint_cause!=CAUSE_REJECTED && e_multipoint_cause!=CAUSE_NORMAL) /* no L1 */
2387 e_multipoint_cause = CAUSE_OUTOFORDER;
2388 e_multipoint_location = param->disconnectinfo.location;
2390 if (param->disconnectinfo.cause!=CAUSE_NOUSER && e_multipoint_cause!=CAUSE_OUTOFORDER && e_multipoint_cause!=CAUSE_BUSY && e_multipoint_cause!=CAUSE_REJECTED && e_multipoint_cause!=CAUSE_NORMAL) /* anything but not 18 */
2392 e_multipoint_cause = param->disconnectinfo.cause;
2393 e_multipoint_location = param->disconnectinfo.location;
2395 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new multipoint cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location);
2397 /* check if we have more than one portlist relation and we just ignore the disconnect */
2398 if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist->next)
2400 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the disconnect was from a multipoint call. we just release that relation.\n", ea_endpoint->ep_serial);
2401 portlist = ea_endpoint->ep_portlist;
2404 if (portlist->port_id == port_id)
2406 portlist = portlist->next;
2410 PERROR("EPOINT(%d) software error: no portlist related to the calling port.\n", ea_endpoint->ep_serial);
2413 if (message_type != MESSAGE_RELEASE)
2415 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2416 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2417 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2418 message_put(message);
2419 logmessage(message);
2421 ea_endpoint->free_portlist(portlist);
2422 return; /* one relation removed */
2424 if (e_multipoint_cause)
2426 cause = e_multipoint_cause;
2427 location = e_multipoint_location;
2430 cause = param->disconnectinfo.cause;
2431 location = param->disconnectinfo.location;
2434 e_cfnr_call = e_cfnr_release = 0;
2436 /* process hangup */
2437 process_hangup(e_call_cause, e_call_location);
2438 e_multipoint_cause = 0;
2439 e_multipoint_location = LOCATION_PRIVATE_LOCAL;
2441 /* tone to disconnected end */
2442 SPRINT(buffer, "cause_%02x", cause);
2443 if (ea_endpoint->ep_portlist)
2444 set_tone(ea_endpoint->ep_portlist, buffer);
2446 new_state(EPOINT_STATE_IN_DISCONNECT);
2447 if (ea_endpoint->ep_call_id)
2449 int haspatterns = 0;
2450 /* check if pattern is available */
2451 if (ea_endpoint->ep_portlist)
2452 if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->earlyb)
2453 #warning wie ist das bei einem asterisk, gibts auch tones?
2454 if (callpbx_countrelations(ea_endpoint->ep_call_id)==2 // we must count relations, in order not to disturb the conference ; NOTE:
2455 && message_type != MESSAGE_RELEASE) // if we release, we are done
2459 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has patterns.\n", ea_endpoint->ep_serial);
2460 /* indicate patterns */
2461 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_PATTERN);
2462 message_put(message);
2463 /* connect audio, if not already */
2464 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2465 message->param.channel = CHANNEL_STATE_CONNECT;
2466 message_put(message);
2467 /* send disconnect */
2468 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
2469 memcpy(&message->param, param, sizeof(union parameter));
2470 message_put(message);
2471 /* disable encryption if disconnected */
2472 //PERROR("REMOVE ME: state =%d, %d\n", e_crypt_state, e_crypt);
2474 cryptman_message(CI_DISCONNECT_IND, NULL, 0);
2478 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
2481 release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, callcause, portcause */
2482 return; /* must exit here */
2485 /* port MESSAGE_TIMEOUT */
2486 void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type, union parameter *param)
2490 printlog("%3d incoming TIMEOUT\n",
2491 ea_endpoint->ep_serial
2493 message_type = MESSAGE_DISCONNECT;
2494 switch (param->state)
2496 case PORT_STATE_OUT_SETUP:
2497 case PORT_STATE_OUT_OVERLAP:
2498 /* no user responding */
2499 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2500 return; /* must exit here */
2502 case PORT_STATE_IN_SETUP:
2503 case PORT_STATE_IN_OVERLAP:
2504 param->disconnectinfo.cause = CAUSE_INVALID; /* number incomplete */
2505 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2508 case PORT_STATE_OUT_PROCEEDING:
2509 param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
2510 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2511 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2512 return; /* must exit here */
2514 case PORT_STATE_IN_PROCEEDING:
2515 param->disconnectinfo.cause = CAUSE_NOUSER;
2516 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL; /* no user responding */
2519 case PORT_STATE_OUT_ALERTING:
2520 param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
2521 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2522 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2523 return; /* must exit here */
2525 case PORT_STATE_IN_ALERTING:
2526 param->disconnectinfo.cause = CAUSE_NOANSWER;
2527 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2530 case PORT_STATE_IN_DISCONNECT:
2531 case PORT_STATE_OUT_DISCONNECT:
2532 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
2533 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2534 return; /* must exit here */
2537 param->disconnectinfo.cause = 31; /* normal unspecified */
2538 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2540 /* release call, disconnect isdn */
2542 new_state(EPOINT_STATE_OUT_DISCONNECT);
2543 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2544 SCPY(e_tone, cause);
2547 set_tone(portlist, cause);
2548 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2549 portlist = portlist->next;
2551 release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
2554 /* port MESSAGE_NOTIFY */
2555 void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, union parameter *param)
2557 struct message *message;
2561 /* signal to call tool */
2562 admin_call_response(e_adminid, ADMIN_CALL_NOTIFY, numberrize_callerinfo(param->notifyinfo.id,param->notifyinfo.ntype), 0, 0, param->notifyinfo.notify);
2563 if (param->notifyinfo.notify)
2565 e_rx_state = track_notify(e_rx_state, param->notifyinfo.notify);
2568 /* if we get notification from stack, local shows if we disabled/enabled audio stream */
2569 if (param->notifyinfo.local) switch(param->notifyinfo.notify)
2571 case INFO_NOTIFY_REMOTE_HOLD:
2572 case INFO_NOTIFY_USER_SUSPENDED:
2573 /* tell call about it */
2574 if (ea_endpoint->ep_call_id)
2576 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2577 message->param.channel = CHANNEL_STATE_HOLD;
2578 message_put(message);
2582 case INFO_NOTIFY_REMOTE_RETRIEVAL:
2583 case INFO_NOTIFY_USER_RESUMED:
2584 /* set volume of rx and tx */
2585 if (param->setup.callerinfo.itype == INFO_ITYPE_INTERN)
2586 if (e_ext.txvol!=256 || e_ext.rxvol!=256)
2589 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2590 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2591 message->param.mISDNsignal.rxvol = e_ext.txvol;
2592 message->param.mISDNsignal.txvol = e_ext.rxvol;
2593 message_put(message);
2595 /* set current tone */
2597 set_tone(portlist, e_tone);
2598 /* tell call about it */
2599 if (ea_endpoint->ep_call_id)
2601 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2602 message->param.channel = CHANNEL_STATE_CONNECT;
2603 message_put(message);
2608 /* get name of notify */
2609 switch(param->notifyinfo.notify)
2615 logtext = "USER_SUSPENDED";
2618 logtext = "BEARER_SERVICE_CHANGED";
2621 logtext = "USER_RESUMED";
2624 logtext = "CONFERENCE_ESTABLISHED";
2627 logtext = "CONFERENCE_DISCONNECTED";
2630 logtext = "OTHER_PARTY_ADDED";
2633 logtext = "ISOLATED";
2636 logtext = "REATTACHED";
2639 logtext = "OTHER_PARTY_ISOLATED";
2642 logtext = "OTHER_PARTY_REATTACHED";
2645 logtext = "OTHER_PARTY_SPLIT";
2648 logtext = "OTHER_PARTY_DISCONNECTED";
2651 logtext = "CONFERENCE_FLOATING";
2654 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
2657 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
2660 logtext = "CALL_IS_A_WAITING_CALL";
2663 logtext = "DIVERSION_ACTIVATED";
2666 logtext = "RESERVED_CT_1";
2669 logtext = "RESERVED_CT_2";
2672 logtext = "REVERSE_CHARGING";
2675 logtext = "REMOTE_HOLD";
2678 logtext = "REMOTE_RETRIEVAL";
2681 logtext = "CALL_IS_DIVERTING";
2684 SPRINT(buffer, "indicator=%d", param->notifyinfo.notify - 0x80);
2688 printlog("%3d incoming NOTIFY notify='%s' id='%s'%s\n",
2689 ea_endpoint->ep_serial,
2691 param->notifyinfo.id,
2692 (param->notifyinfo.present==INFO_PRESENT_RESTRICTED)?" anonymous":""
2695 /* notify call if available */
2696 if (ea_endpoint->ep_call_id)
2698 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_NOTIFY);
2699 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
2700 message_put(message);
2705 /* port MESSAGE_FACILITY */
2706 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
2708 struct message *message;
2710 printlog("%3d incoming FACILITY len='%d'\n",
2711 ea_endpoint->ep_serial,
2712 param->facilityinfo.len
2715 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_FACILITY);
2716 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2717 message_put(message);
2720 /* port MESSAGE_SUSPEND */
2721 /* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
2722 void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
2724 printlog("%3d incoming SUSPEND\n",
2725 ea_endpoint->ep_serial
2727 /* epoint is now parked */
2728 ea_endpoint->ep_park = 1;
2729 memcpy(ea_endpoint->ep_park_callid, param->parkinfo.callid, sizeof(ea_endpoint->ep_park_callid));
2730 ea_endpoint->ep_park_len = (param->parkinfo.len>8)?8:param->parkinfo.len;
2732 /* remove port relation */
2733 ea_endpoint->free_portlist(portlist);
2736 /* port MESSAGE_RESUME */
2737 /* NOTE: before resume, the active-notification must be done in order to set call mixer */
2738 void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
2740 printlog("%3d incoming RESUME\n",
2741 ea_endpoint->ep_serial
2743 /* epoint is now resumed */
2744 ea_endpoint->ep_park = 0;
2749 /* port sends message to the endpoint
2751 void EndpointAppPBX::ea_message_port(unsigned long port_id, int message_type, union parameter *param)
2753 struct port_list *portlist;
2754 struct message *message;
2757 portlist = ea_endpoint->ep_portlist;
2760 if (port_id == portlist->port_id)
2762 portlist = portlist->next;
2766 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);
2770 // PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
2771 switch(message_type)
2773 case MESSAGE_DATA: /* data from port */
2774 /* send back to source for recording */
2777 message = message_create(ea_endpoint->ep_serial, port_id, EPOINT_TO_PORT, message_type);
2778 memcpy(&message->param, param, sizeof(union parameter));
2779 message_put(message);
2782 /* check if there is a call */
2783 if (!ea_endpoint->ep_call_id)
2785 /* continue if only one portlist */
2786 if (ea_endpoint->ep_portlist->next != NULL)
2788 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
2789 memcpy(&message->param, param, sizeof(union parameter));
2790 message_put(message);
2793 case MESSAGE_TONE_EOF: /* tone is end of file */
2794 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
2797 if (e_action->index == ACTION_VBOX_PLAY)
2801 if (e_action->index == ACTION_EFI)
2808 case MESSAGE_TONE_COUNTER: /* counter info received */
2809 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);
2811 if (e_action->index == ACTION_VBOX_PLAY)
2813 e_vbox_counter = param->counter.current;
2814 if (param->counter.max >= 0)
2815 e_vbox_counter_max = param->counter.max;
2819 /* PORT sends SETUP message */
2821 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call from callerid=%s, dialing=%s\n", ea_endpoint->ep_serial, param->setup.callerinfo.id, param->setup.dialinginfo.number);
2822 if (e_state!=EPOINT_STATE_IDLE)
2824 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
2827 port_setup(portlist, message_type, param);
2830 /* PORT sends INFORMATION message */
2831 case MESSAGE_INFORMATION: /* additional digits received */
2832 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call dialing more=%s (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, param->information.number, e_ext.number, e_callerinfo.id);
2833 port_information(portlist, message_type, param);
2836 /* PORT sends FACILITY message */
2837 case MESSAGE_FACILITY:
2838 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2839 port_facility(portlist, message_type, param);
2842 /* PORT sends DTMF message */
2843 case MESSAGE_DTMF: /* dtmf digits received */
2844 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);
2845 port_dtmf(portlist, message_type, param);
2848 /* PORT sends CRYPT message */
2849 case MESSAGE_CRYPT: /* crypt response received */
2850 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) crypt response=%d\n", ea_endpoint->ep_serial, param->crypt.type);
2851 port_crypt(portlist, message_type, param);
2854 /* PORT sends MORE message */
2855 case MESSAGE_OVERLAP:
2856 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);
2857 if (e_state != EPOINT_STATE_OUT_SETUP)
2859 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);
2862 port_overlap(portlist, message_type, param);
2865 /* PORT sends PROCEEDING message */
2866 case MESSAGE_PROCEEDING: /* port is proceeding */
2867 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);
2868 if (e_state!=EPOINT_STATE_OUT_SETUP
2869 && e_state!=EPOINT_STATE_OUT_OVERLAP)
2871 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);
2874 port_proceeding(portlist, message_type, param);
2877 /* PORT sends ALERTING message */
2878 case MESSAGE_ALERTING:
2879 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);
2880 if (e_state!=EPOINT_STATE_OUT_SETUP
2881 && e_state!=EPOINT_STATE_OUT_OVERLAP
2882 && e_state!=EPOINT_STATE_OUT_PROCEEDING)
2884 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);
2887 port_alerting(portlist, message_type, param);
2890 /* PORT sends CONNECT message */
2891 case MESSAGE_CONNECT:
2892 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);
2893 if (e_state!=EPOINT_STATE_OUT_SETUP
2894 && e_state!=EPOINT_STATE_OUT_OVERLAP
2895 && e_state!=EPOINT_STATE_OUT_PROCEEDING
2896 && e_state!=EPOINT_STATE_OUT_ALERTING)
2898 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
2901 port_connect(portlist, message_type, param);
2904 /* PORT sends DISCONNECT message */
2905 case MESSAGE_DISCONNECT: /* port is disconnected */
2906 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);
2907 port_disconnect_release(portlist, message_type, param);
2910 /* PORT sends a RELEASE message */
2911 case MESSAGE_RELEASE: /* port releases */
2912 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);
2913 /* portlist is release at port_disconnect_release, thanx Paul */
2914 port_disconnect_release(portlist, message_type, param);
2917 /* PORT sends a TIMEOUT message */
2918 case MESSAGE_TIMEOUT:
2919 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);
2920 port_timeout(portlist, message_type, param);
2921 break; /* release */
2923 /* PORT sends a NOTIFY message */
2924 case MESSAGE_NOTIFY:
2925 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);
2926 port_notify(portlist, message_type, param);
2929 /* PORT sends a SUSPEND message */
2930 case MESSAGE_SUSPEND:
2931 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);
2932 port_suspend(portlist, message_type, param);
2933 break; /* suspend */
2935 /* PORT sends a RESUME message */
2936 case MESSAGE_RESUME:
2937 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);
2938 port_resume(portlist, message_type, param);
2942 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);
2945 /* Note: this endpoint may be destroyed, so we MUST return */
2949 /* messages from port
2951 /* call MESSAGE_CRYPT */
2952 void EndpointAppPBX::call_crypt(struct port_list *portlist, int message_type, union parameter *param)
2954 switch(param->crypt.type)
2956 /* message from remote port to "crypt manager" */
2957 case CU_ACTK_REQ: /* activate key-exchange */
2958 case CU_ACTS_REQ: /* activate shared key */
2959 case CU_DACT_REQ: /* deactivate */
2960 case CU_INFO_REQ: /* request last info message */
2961 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2964 /* message from "crypt manager" to user */
2965 case CU_ACTK_CONF: /* key-echange done */
2966 case CU_ACTS_CONF: /* shared key done */
2967 case CU_DACT_CONF: /* deactivated */
2968 case CU_DACT_IND: /* deactivated */
2969 case CU_ERROR_IND: /* receive error message */
2970 case CU_INFO_IND: /* receive info message */
2971 case CU_INFO_CONF: /* receive info message */
2972 encrypt_result(param->crypt.type, (char *)param->crypt.data);
2976 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);
2980 /* call MESSAGE_INFORMATION */
2981 void EndpointAppPBX::call_information(struct port_list *portlist, int message_type, union parameter *param)
2983 struct message *message;
2989 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2990 memcpy(&message->param.information, ¶m->information, sizeof(struct dialing_info));
2991 message_put(message);
2992 logmessage(message);
2993 portlist = portlist->next;
2997 /* call MESSAGE_FACILITY */
2998 void EndpointAppPBX::call_facility(struct port_list *portlist, int message_type, union parameter *param)
3000 struct message *message;
3002 if (!e_ext.facility)
3009 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_FACILITY);
3010 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
3011 message_put(message);
3012 logmessage(message);
3013 portlist = portlist->next;
3017 /* call MESSAGE_MORE */
3018 void EndpointAppPBX::call_overlap(struct port_list *portlist, int message_type, union parameter *param)
3020 struct message *message;
3022 new_state(EPOINT_STATE_IN_OVERLAP);
3025 if (e_call_pattern && e_ext.own_setup)
3027 /* disconnect audio */
3028 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3029 message->param.channel = CHANNEL_STATE_HOLD;
3030 message_put(message);
3032 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
3034 set_tone(portlist, "dialtone");
3037 if (e_ext.number[0])
3038 set_tone(portlist, "dialpbx");
3040 set_tone(portlist, "dialtone");
3043 /* call MESSAGE_PROCEEDING */
3044 void EndpointAppPBX::call_proceeding(struct port_list *portlist, int message_type, union parameter *param)
3046 struct message *message;
3048 new_state(EPOINT_STATE_IN_PROCEEDING);
3050 /* own proceeding tone */
3053 /* connect / disconnect audio */
3054 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3055 if (e_ext.own_proceeding)
3056 message->param.channel = CHANNEL_STATE_HOLD;
3058 message->param.channel = CHANNEL_STATE_CONNECT;
3059 message_put(message);
3061 // UCPY(e_call_tone, "proceeding");
3064 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3065 message_put(message);
3066 logmessage(message);
3068 set_tone(portlist, "proceeding");
3071 /* call MESSAGE_ALERTING */
3072 void EndpointAppPBX::call_alerting(struct port_list *portlist, int message_type, union parameter *param)
3074 struct message *message;
3076 new_state(EPOINT_STATE_IN_ALERTING);
3078 /* own alerting tone */
3081 /* connect / disconnect audio */
3082 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3083 if (e_ext.own_alerting)
3084 message->param.channel = CHANNEL_STATE_HOLD;
3086 message->param.channel = CHANNEL_STATE_CONNECT;
3087 message_put(message);
3091 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
3092 message_put(message);
3093 logmessage(message);
3095 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
3097 set_tone(portlist, "ringing");
3100 if (e_ext.number[0])
3101 set_tone(portlist, "ringpbx");
3103 set_tone(portlist, "ringing");
3106 /* call MESSAGE_CONNECT */
3107 void EndpointAppPBX::call_connect(struct port_list *portlist, int message_type, union parameter *param)
3109 struct message *message;
3111 new_state(EPOINT_STATE_CONNECT);
3112 // UCPY(e_call_tone, "");
3113 if (e_ext.number[0])
3114 e_dtmf = 1; /* allow dtmf */
3116 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_callerinfo));
3119 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3120 memcpy(&message->param, param, sizeof(union parameter));
3121 /* screen by interface */
3122 if (e_connectinfo.interface[0])
3124 /* screen incoming caller id */
3125 screen(1, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present);
3127 memcpy(&message->param.connnectinfo, e_connectinfo);
3129 /* screen clip if prefix is required */
3130 if (e_ext.number[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0])
3132 SCPY(message->param.connectinfo.id, e_ext.clip_prefix);
3133 SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype));
3134 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
3137 /* use internal caller id */
3138 if (e_ext.number[0] && e_connectinfo.intern[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
3140 SCPY(message->param.connectinfo.id, e_connectinfo.intern);
3141 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
3144 /* handle restricted caller ids */
3145 apply_callerid_restriction(e_ext.anon_ignore, portlist->port_type, message->param.connectinfo.id, &message->param.connectinfo.ntype, &message->param.connectinfo.present, &message->param.connectinfo.screen, message->param.connectinfo.voip, message->param.connectinfo.intern, message->param.connectinfo.name);
3146 /* display callerid if desired for extension */
3147 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.voip, message->param.connectinfo.intern, message->param.connectinfo.name));
3149 /* use conp, if enabld */
3151 message->param.connectinfo.name[0] = '\0';
3154 message_put(message);
3155 logmessage(message);
3157 set_tone(portlist, NULL);
3159 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3160 message->param.channel = CHANNEL_STATE_CONNECT;
3161 message_put(message);
3165 /* call MESSAGE_DISCONNECT MESSAGE_RELEASE */
3166 void EndpointAppPBX::call_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
3169 struct message *message;
3172 /* be sure that we are active */
3174 e_tx_state = NOTIFY_STATE_ACTIVE;
3176 /* we are powerdialing, if e_powerdialing is set and limit is not exceeded if given */
3177 if (e_powerdialing && ((e_powercount+1)<e_powerlimit || e_powerlimit<1))
3179 release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
3181 /* set time for power dialing */
3182 e_powerdialing = now_d + e_powerdelay; /* set redial in the future */
3185 /* set redial tone */
3186 if (ea_endpoint->ep_portlist)
3190 set_tone(ea_endpoint->ep_portlist, "redial");
3191 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);
3192 /* send proceeding when powerdialing and still setup (avoid dialing timeout) */
3193 if (e_state==EPOINT_STATE_IN_OVERLAP)
3195 new_state(EPOINT_STATE_IN_PROCEEDING);
3198 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3199 message_put(message);
3200 logmessage(message);
3202 /* caused the error, that the first knock sound was not there */
3203 /* set_tone(portlist, "proceeding"); */
3205 /* send display of powerdialing */
3206 if (e_ext.display_dialing)
3210 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3212 SPRINT(message->param.notifyinfo.display, "Retry %d of %d", e_powercount, e_powerlimit);
3214 SPRINT(message->param.notifyinfo.display, "Retry %d", e_powercount);
3215 message_put(message);
3216 logmessage(message);
3217 portlist = portlist->next;
3226 if ((e_state!=EPOINT_STATE_CONNECT
3227 && e_state!=EPOINT_STATE_OUT_DISCONNECT
3228 && e_state!=EPOINT_STATE_IN_OVERLAP
3229 && e_state!=EPOINT_STATE_IN_PROCEEDING
3230 && e_state!=EPOINT_STATE_IN_ALERTING)
3231 || !ea_endpoint->ep_portlist) /* or no port */
3233 process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
3234 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause); /* RELEASE_TYPE, call, port */
3235 return; /* must exit here */
3240 e_call_cause = param->disconnectinfo.cause;
3241 e_call_location = param->disconnectinfo.location;
3244 /* on release we need the audio again! */
3245 if (message_type == MESSAGE_RELEASE)
3248 ea_endpoint->ep_call_id = 0;
3250 /* disconnect and select tone */
3251 new_state(EPOINT_STATE_OUT_DISCONNECT);
3252 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
3253 /* if own_cause, we must release the call */
3254 if (e_ext.own_cause /* own cause */
3255 || !e_call_pattern) /* no patterns */
3257 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_call_pattern);
3258 if (message_type != MESSAGE_RELEASE)
3259 release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
3261 } else /* else we enable audio */
3263 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3264 message->param.channel = CHANNEL_STATE_CONNECT;
3265 message_put(message);
3267 /* send disconnect message */
3268 SCPY(e_tone, cause);
3271 set_tone(portlist, cause);
3272 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
3273 portlist = portlist->next;
3277 /* call MESSAGE_SETUP */
3278 void EndpointAppPBX::call_setup(struct port_list *portlist, int message_type, union parameter *param)
3280 struct message *message;
3282 /* if we already in setup state, we just update the dialing with new digits */
3283 if (e_state == EPOINT_STATE_OUT_SETUP
3284 || e_state == EPOINT_STATE_OUT_OVERLAP)
3286 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we are in setup state, so we do overlap dialing.\n", ea_endpoint->ep_serial);
3287 /* if digits changed, what we have already dialed */
3288 if (!!strncmp(e_dialinginfo.number,param->setup.dialinginfo.number,strlen(e_dialinginfo.number)))
3290 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);
3291 /* release all ports */
3292 while((portlist = ea_endpoint->ep_portlist))
3294 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
3295 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
3296 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3297 message_put(message);
3298 logmessage(message);
3299 ea_endpoint->free_portlist(portlist);
3302 /* disconnect audio */
3303 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3304 message->param.channel = CHANNEL_STATE_HOLD;
3305 message_put(message);
3307 /* get dialing info */
3308 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3309 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3310 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3311 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3312 new_state(EPOINT_STATE_OUT_OVERLAP);
3315 e_redial = now_d + 1; /* set redial one second in the future */
3318 /* if we have a pending redial, so we just adjust the dialing number */
3321 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) redial in progress, so we update the dialing number to %s.\n", ea_endpoint->ep_serial, param->setup.dialinginfo.number);
3322 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3325 if (!ea_endpoint->ep_portlist)
3327 PERROR("ERROR: overlap dialing to a NULL port relation\n");
3329 if (ea_endpoint->ep_portlist->next)
3331 PERROR("ERROR: overlap dialing to a port_list port relation\n");
3333 if (e_state == EPOINT_STATE_OUT_SETUP)
3336 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.number);
3337 SCAT(e_dialing_queue, param->setup.dialinginfo.number + strlen(e_dialinginfo.number));
3341 /* get what we have not dialed yet */
3342 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have already dialed '%s', we received '%s', what's left '%s'.\n", ea_endpoint->ep_serial, e_dialinginfo.number, param->setup.dialinginfo.number, param->setup.dialinginfo.number+strlen(e_dialinginfo.number));
3343 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
3344 SCPY(message->param.information.number, param->setup.dialinginfo.number + strlen(e_dialinginfo.number));
3345 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
3346 message_put(message);
3347 logmessage(message);
3349 /* always store what we have dialed or queued */
3350 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3354 if (e_state != EPOINT_STATE_IDLE)
3356 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
3359 /* if an internal extension is dialed, copy that number */
3360 if (param->setup.dialinginfo.itype==INFO_ITYPE_INTERN || param->setup.dialinginfo.itype==INFO_ITYPE_VBOX)
3361 SCPY(e_ext.number, param->setup.dialinginfo.number);
3362 /* if an internal extension is dialed, get extension's info about caller */
3363 if (e_ext.number[0])
3365 if (!read_extension(&e_ext, e_ext.number))
3367 e_ext.number[0] = '\0';
3368 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the called terminal='%s' is not found in directory tree!\n", ea_endpoint->ep_serial, e_ext.number);
3372 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3373 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3374 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3375 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3377 /* screen by interface */
3378 if (e_callerinfo.interface[0])
3380 /* screen incoming caller id */
3381 screen(1, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present);
3384 /* process (voice over) data calls */
3385 if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO)
3387 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) handling data call as audio call: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
3388 memset(&e_capainfo, 0, sizeof(e_capainfo));
3389 e_capainfo.bearer_capa = INFO_BC_AUDIO;
3390 e_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
3391 e_capainfo.bearer_info1 = (options.law=='u')?INFO_INFO1_ULAW:INFO_INFO1_ALAW;
3394 new_state(EPOINT_STATE_OUT_SETUP);
3395 /* call special setup routine */
3399 /* call MESSAGE_mISDNSIGNAL */
3400 void EndpointAppPBX::call_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param)
3402 struct message *message;
3406 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
3407 memcpy(&message->param, param, sizeof(union parameter));
3408 message_put(message);
3409 portlist = portlist->next;
3413 /* call MESSAGE_NOTIFY */
3414 void EndpointAppPBX::call_notify(struct port_list *portlist, int message_type, union parameter *param)
3416 struct message *message;
3419 if (param->notifyinfo.notify)
3421 new_state = track_notify(e_tx_state, param->notifyinfo.notify);
3422 // /* if notification was generated locally, we turn hold music on/off */
3423 // if (param->notifyinfo.local)
3424 // 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)
3429 if (new_state!=NOTIFY_STATE_HOLD && new_state!=NOTIFY_STATE_SUSPEND)
3433 set_tone(portlist, "");
3434 portlist = portlist->next;
3436 portlist = ea_endpoint->ep_portlist;
3441 if (new_state==NOTIFY_STATE_HOLD || new_state==NOTIFY_STATE_SUSPEND)
3445 set_tone(portlist, "hold");
3446 portlist = portlist->next;
3448 portlist = ea_endpoint->ep_portlist;
3453 /* save new state */
3454 e_tx_state = new_state;
3457 /* notify port(s) about it */
3460 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3461 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
3462 /* handle restricted caller ids */
3463 apply_callerid_restriction(e_ext.anon_ignore, portlist->port_type, message->param.notifyinfo.id, &message->param.notifyinfo.ntype, &message->param.notifyinfo.present, NULL, message->param.notifyinfo.voip, message->param.notifyinfo.intern, 0);
3464 /* display callerid if desired for extension */
3465 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.voip, message->param.notifyinfo.intern, NULL));
3466 message_put(message);
3467 logmessage(message);
3468 portlist = portlist->next;
3472 /* call sends messages to the endpoint
3474 void EndpointAppPBX::ea_message_call(unsigned long call_id, int message_type, union parameter *param)
3476 struct port_list *portlist;
3477 struct message *message;
3481 PERROR("EPOINT(%d) error: call == NULL.\n", ea_endpoint->ep_serial);
3485 portlist = ea_endpoint->ep_portlist;
3487 /* send MESSAGE_DATA to port */
3488 if (call_id == ea_endpoint->ep_call_id)
3490 if (message_type == MESSAGE_DATA)
3492 /* skip if no port relation */
3495 /* skip if more than one port relation */
3498 /* send audio data to port */
3499 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DATA);
3500 memcpy(&message->param, param, sizeof(union parameter));
3501 message_put(message);
3506 // PDEBUG(DEBUG_EPOINT, "EPOINT(%d) received message %d for active call (terminal %s, caller id %s state=%d)\n", ea_endpoint->ep_serial, message, e_ext.number, e_callerinfo.id, e_state);
3507 switch(message_type)
3509 /* CALL SENDS CRYPT message */
3511 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);
3512 call_crypt(portlist, message_type, param);
3515 /* CALL sends INFORMATION message */
3516 case MESSAGE_INFORMATION:
3517 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.number);
3518 call_information(portlist, message_type, param);
3521 /* CALL sends FACILITY message */
3522 case MESSAGE_FACILITY:
3523 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);
3524 call_facility(portlist, message_type, param);
3527 /* CALL sends OVERLAP message */
3528 case MESSAGE_OVERLAP:
3529 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);
3530 if (e_state!=EPOINT_STATE_IN_SETUP
3531 && e_state!=EPOINT_STATE_IN_OVERLAP)
3533 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3536 call_overlap(portlist, message_type, param);
3539 /* CALL sends PROCEEDING message */
3540 case MESSAGE_PROCEEDING:
3541 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);
3542 if(e_state!=EPOINT_STATE_IN_OVERLAP)
3544 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3547 call_proceeding(portlist, message_type, param);
3550 /* CALL sends ALERTING message */
3551 case MESSAGE_ALERTING:
3552 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);
3553 if (e_state!=EPOINT_STATE_IN_OVERLAP
3554 && e_state!=EPOINT_STATE_IN_PROCEEDING)
3556 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state.\n", ea_endpoint->ep_serial);
3559 call_alerting(portlist, message_type, param);
3562 /* CALL sends CONNECT message */
3563 case MESSAGE_CONNECT:
3564 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);
3565 if (e_state!=EPOINT_STATE_IN_OVERLAP
3566 && e_state!=EPOINT_STATE_IN_PROCEEDING
3567 && e_state!=EPOINT_STATE_IN_ALERTING)
3569 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
3572 call_connect(portlist, message_type, param);
3575 /* CALL sends DISCONNECT/RELEASE message */
3576 case MESSAGE_DISCONNECT: /* call disconnect */
3577 case MESSAGE_RELEASE: /* call releases */
3578 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);
3579 call_disconnect_release(portlist, message_type, param);
3582 /* CALL sends SETUP message */
3584 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.intern, param->setup.callerinfo.id, param->setup.dialinginfo.number, param->setup.dialinginfo.itype);
3585 call_setup(portlist, message_type, param);
3589 /* CALL sends special mISDNSIGNAL message */
3590 case MESSAGE_mISDNSIGNAL: /* isdn message to port */
3591 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);
3592 call_mISDNsignal(portlist, message_type, param);
3595 /* CALL has pattern available */
3596 case MESSAGE_PATTERN: /* indicating pattern available */
3597 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);
3598 if (!e_call_pattern)
3600 PDEBUG(DEBUG_EPOINT, "-> pattern becomes available\n");
3605 set_tone(portlist, NULL);
3606 portlist = portlist->next;
3608 /* connect our audio tx and rx (blueboxing should be possibe before connect :)*/
3609 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3610 message->param.channel = CHANNEL_STATE_CONNECT;
3611 message_put(message);
3612 // /* tell remote epoint to connect audio also, because we like to hear the patterns */
3613 // message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_REMOTE_AUDIO);
3614 // message->param.channel = CHANNEL_STATE_CONNECT;
3615 // message_put(message);
3616 // patterns are available, remote already connected audio
3620 /* CALL has no pattern available */
3621 case MESSAGE_NOPATTERN: /* indicating no pattern available */
3622 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);
3625 PDEBUG(DEBUG_EPOINT, "-> pattern becomes unavailable\n");
3627 /* disconnect our audio tx and rx */
3628 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3629 message->param.channel = CHANNEL_STATE_HOLD;
3630 message_put(message);
3635 /* CALL (dunno at the moment) */
3636 case MESSAGE_REMOTE_AUDIO:
3637 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);
3638 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3639 message->param.channel = param->channel;
3640 message_put(message);
3644 /* CALL sends a notify message */
3645 case MESSAGE_NOTIFY:
3646 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);
3647 call_notify(portlist, message_type, param);
3651 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);
3656 /* pick_call will connect the first incoming call found. the endpoint
3657 * will receivce a MESSAGE_CONNECT.
3659 int match_list(char *list, char *item)
3661 char *end, *next = NULL;
3663 /* no list make matching */
3669 /* eliminate white spaces */
3670 while (*list <= ' ')
3677 /* if end of list is reached, we return */
3678 if (list[0] == '\0')
3680 /* if we have more than one entry (left) */
3681 if ((end = strchr(list, ',')))
3684 next = end = strchr(list, '\0');
3685 while (*(end-1) <= ' ')
3687 /* if string part matches item */
3688 if (!strncmp(list, item, end-list))
3694 void EndpointAppPBX::pick_call(char *extensions)
3696 struct message *message;
3697 struct port_list *portlist;
3699 class EndpointAppPBX *eapp, *found;
3701 class CallPBX *callpbx;
3702 struct call_relation *relation;
3705 /* find an endpoint that is ringing internally or vbox with higher priority */
3708 eapp = apppbx_first;
3711 if (eapp!=this && ea_endpoint->ep_portlist)
3713 portlist = eapp->ea_endpoint->ep_portlist;
3716 if ((port = find_port_id(portlist->port_id)))
3718 if (port->p_type == PORT_TYPE_VBOX_OUT)
3720 if (match_list(extensions, eapp->e_ext.number))
3727 if ((port->p_type==PORT_TYPE_DSS1_NT_OUT || port->p_type==PORT_TYPE_DSS1_TE_OUT)
3728 && port->p_state==PORT_STATE_OUT_ALERTING)
3729 if (match_list(extensions, eapp->e_ext.number))
3734 portlist = portlist->next;
3742 /* if no endpoint found */
3745 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);
3747 set_tone(ea_endpoint->ep_portlist, "cause_10");
3748 message_disconnect_port(ea_endpoint->ep_portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
3749 new_state(EPOINT_STATE_OUT_DISCONNECT);
3754 if (ea_endpoint->ep_call_id)
3756 PERROR("EPOINT(%d) we already have a call. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3759 if (!eapp->ea_endpoint->ep_call_id)
3761 PERROR("EPOINT(%d) ringing endpoint has no call.\n", ea_endpoint->ep_serial);
3764 call = find_call_id(eapp->ea_endpoint->ep_call_id);
3767 PERROR("EPOINT(%d) ringing endpoint's call not found.\n", ea_endpoint->ep_serial);
3770 if (callpbx->c_type != CALL_TYPE_PBX)
3772 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ringing endpoint's call is not a PBX call, so we must reject.\n", ea_endpoint->ep_serial);
3775 callpbx = (class CallPBX *)call;
3776 relation = callpbx->c_relation;
3779 PERROR("EPOINT(%d) ringing endpoint's call has no relation. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3782 while (relation->epoint_id != eapp->ea_endpoint->ep_serial)
3784 relation = relation->next;
3787 PERROR("EPOINT(%d) ringing endpoint's call has no relation to that call. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3792 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found ringing endpoint: %d.\n", ea_endpoint->ep_serial, eapp->ea_endpoint->ep_serial);
3794 if (options.deb & DEBUG_EPOINT)
3796 class Call *debug_c = call_first;
3797 class Endpoint *debug_e = epoint_first;
3798 class Port *debug_p = port_first;
3800 callpbx_debug(callpbx, "EndpointAppPBX::pick_call(before)");
3802 PDEBUG(DEBUG_EPOINT, "showing all calls:\n");
3805 PDEBUG(DEBUG_EPOINT, "call=%ld\n", debug_c->c_serial);
3806 debug_c = debug_c->next;
3808 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3811 PDEBUG(DEBUG_EPOINT, "ep=%ld, call=%ld\n", debug_e->ep_serial, debug_e->ep_call_id);
3812 debug_e = debug_e->next;
3814 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3817 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld (active)\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3818 debug_p = debug_p->next;
3823 ea_endpoint->ep_call_id = eapp->ea_endpoint->ep_call_id; /* we get the call */
3824 relation->epoint_id = ea_endpoint->ep_serial; /* the call gets us */
3825 eapp->ea_endpoint->ep_call_id = 0; /* the ringing endpoint will get disconnected */
3827 /* connnecting our endpoint */
3828 new_state(EPOINT_STATE_CONNECT);
3830 set_tone(ea_endpoint->ep_portlist, NULL);
3832 /* now we send a release to the ringing endpoint */
3833 message = message_create(ea_endpoint->ep_call_id, eapp->ea_endpoint->ep_serial, CALL_TO_EPOINT, MESSAGE_RELEASE);
3834 message->param.disconnectinfo.cause = 26; /* non selected user clearing */
3835 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3836 message_put(message);
3838 /* we send a connect to the call with our caller id */
3839 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CONNECT);
3840 SCPY(message->param.connectinfo.id, e_callerinfo.id);
3841 message->param.connectinfo.present = e_callerinfo.present;
3842 message->param.connectinfo.screen = e_callerinfo.screen;
3843 message->param.connectinfo.itype = e_callerinfo.itype;
3844 message->param.connectinfo.ntype = e_callerinfo.ntype;
3845 message_put(message);
3847 /* we send a connect to our port with the remote callerid */
3848 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3849 SCPY(message->param.connectinfo.id, eapp->e_callerinfo.id);
3850 message->param.connectinfo.present = eapp->e_callerinfo.present;
3851 message->param.connectinfo.screen = eapp->e_callerinfo.screen;
3852 message->param.connectinfo.itype = eapp->e_callerinfo.itype;
3853 message->param.connectinfo.ntype = eapp->e_callerinfo.ntype;
3854 /* handle restricted caller ids */
3855 apply_callerid_restriction(e_ext.anon_ignore, ea_endpoint->ep_portlist->port_type, message->param.connectinfo.id, &message->param.connectinfo.ntype, &message->param.connectinfo.present, &message->param.connectinfo.screen, message->param.connectinfo.voip, message->param.connectinfo.intern, message->param.connectinfo.name);
3856 /* display callerid if desired for extension */
3857 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.voip, message->param.connectinfo.intern, message->param.connectinfo.name));
3858 message_put(message);
3860 /* we send a connect to the audio path (not for vbox) */
3861 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3862 message->param.channel = CHANNEL_STATE_CONNECT;
3863 message_put(message);
3865 /* beeing paranoid, we make call update */
3866 callpbx->c_mixer = 1;
3868 if (options.deb & DEBUG_EPOINT)
3870 class Call *debug_c = call_first;
3871 class Endpoint *debug_e = epoint_first;
3872 class Port *debug_p = port_first;
3874 callpbx_debug(callpbx, "EndpointAppPBX::pick_call(after)");
3876 PDEBUG(DEBUG_EPOINT, "showing all calls:\n");
3879 PDEBUG(DEBUG_EPOINT, "call=%ld\n", debug_c->c_serial);
3880 debug_c = debug_c->next;
3882 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3885 PDEBUG(DEBUG_EPOINT, "ep=%ld, call=%ld\n", debug_e->ep_serial, debug_e->ep_call_id);
3886 debug_e = debug_e->next;
3888 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3891 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3892 debug_p = debug_p->next;
3898 /* join calls (look for a call that is on hold (same isdn interface/terminal))
3900 void EndpointAppPBX::join_call(void)
3902 struct message *message;
3903 struct call_relation *our_relation, *other_relation;
3904 struct call_relation **our_relation_pointer, **other_relation_pointer;
3905 class Call *our_call, *other_call;
3906 class CallPBX *our_callpbx, *other_callpbx;
3907 class EndpointAppPBX *other_eapp; class Endpoint *temp_epoint;
3908 class Port *our_port, *other_port;
3909 class Pdss1 *our_pdss1, *other_pdss1;
3911 /* are we a candidate to join a call */
3912 our_call = find_call_id(ea_endpoint->ep_call_id);
3915 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our call doesn't exist anymore.\n", ea_endpoint->ep_serial);
3918 if (our_call->c_type != CALL_TYPE_PBX)
3920 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: call is not a pbx call.\n", ea_endpoint->ep_serial);
3923 our_callpbx = (class CallPBX *)our_call;
3924 if (!ea_endpoint->ep_portlist)
3926 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
3929 if (!e_ext.number[0])
3931 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
3934 our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
3937 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
3940 if ((our_port->p_type&PORT_CLASS_mISDN_MASK) != PORT_CLASS_mISDN_DSS1)
3942 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not isdn.\n", ea_endpoint->ep_serial);
3945 our_pdss1 = (class Pdss1 *)our_port;
3947 /* find an endpoint that is on hold and has the same mISDNport that we are on */
3948 other_eapp = apppbx_first;
3951 if (other_eapp == this)
3953 other_eapp = other_eapp->next;
3956 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint candiate: (ep%d) terminal='%s' port=%s call=%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_call_id);
3957 if (other_eapp->e_ext.number[0] /* has terminal */
3958 && other_eapp->ea_endpoint->ep_portlist /* has port */
3959 && other_eapp->ea_endpoint->ep_call_id) /* has call */
3961 other_port = find_port_id(other_eapp->ea_endpoint->ep_portlist->port_id);
3962 if (other_port) /* port still exists */
3964 if (other_port->p_type==PORT_TYPE_DSS1_NT_OUT
3965 || other_port->p_type==PORT_TYPE_DSS1_NT_IN) /* port is isdn nt-mode */
3967 other_pdss1 = (class Pdss1 *)other_port;
3968 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);
3969 if (other_pdss1->p_m_hold /* port is on hold */
3970 && other_pdss1->p_m_mISDNport == our_pdss1->p_m_mISDNport /* same isdn interface */
3971 && other_pdss1->p_m_d_ces == our_pdss1->p_m_d_ces) /* same tei+sapi */
3975 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of other type!\n", ea_endpoint->ep_serial);
3979 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port doesn't exist enymore.\n", ea_endpoint->ep_serial);
3982 other_eapp = other_eapp->next;
3986 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn interface with port on hold.\n", ea_endpoint->ep_serial);
3989 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port on hold found.\n", ea_endpoint->ep_serial);
3991 /* if we have the same call */
3992 if (other_eapp->ea_endpoint->ep_call_id == ea_endpoint->ep_call_id)
3994 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we an the other have the same call.\n", ea_endpoint->ep_serial);
3997 other_call = find_call_id(other_eapp->ea_endpoint->ep_call_id);
4000 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other call doesn't exist anymore.\n", ea_endpoint->ep_serial);
4003 if (other_call->c_type != CALL_TYPE_PBX)
4005 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other call is not a pbx call.\n", ea_endpoint->ep_serial);
4008 other_callpbx = (class CallPBX *)other_call;
4009 if (our_callpbx->c_partyline && other_callpbx->c_partyline)
4011 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both calls are partylines.\n", ea_endpoint->ep_serial);
4015 /* remove relation to endpoint for call on hold */
4016 other_relation = other_callpbx->c_relation;
4017 other_relation_pointer = &other_callpbx->c_relation;
4018 while(other_relation)
4020 if (other_relation->epoint_id == other_eapp->ea_endpoint->ep_serial)
4022 /* detach other endpoint on hold */
4023 *other_relation_pointer = other_relation->next;
4024 memset(other_relation, 0, sizeof(struct call_relation));
4025 free(other_relation);
4027 other_relation = *other_relation_pointer;
4028 other_eapp->ea_endpoint->ep_call_id = NULL;
4032 /* change call/hold pointer of endpoint to the new call */
4033 temp_epoint = find_epoint_id(other_relation->epoint_id);
4036 if (temp_epoint->ep_call_id == other_call->c_serial)
4037 temp_epoint->ep_call_id = our_call->c_serial;
4040 other_relation_pointer = &other_relation->next;
4041 other_relation = other_relation->next;
4043 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint on hold removed, other enpoints on call relinked (to our call).\n", ea_endpoint->ep_serial);
4045 /* join call relations */
4046 our_relation = our_callpbx->c_relation;
4047 our_relation_pointer = &our_callpbx->c_relation;
4050 our_relation_pointer = &our_relation->next;
4051 our_relation = our_relation->next;
4053 *our_relation_pointer = other_callpbx->c_relation;
4054 other_callpbx->c_relation = NULL;
4055 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) relations joined.\n", ea_endpoint->ep_serial);
4057 /* release endpoint on hold */
4058 message = message_create(other_callpbx->c_serial, other_eapp->ea_endpoint->ep_serial, CALL_TO_EPOINT, MESSAGE_RELEASE);
4059 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */
4060 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
4061 message_put(message);
4063 /* if we are not a partyline, we get partyline state from other call */
4064 our_callpbx->c_partyline += other_callpbx->c_partyline;
4066 /* remove empty call */
4068 PDEBUG(DEBUG_EPOINT, "EPOINT(%d)d-call completely removed!\n");
4070 /* mixer must update */
4071 our_callpbx->c_mixer = 1; /* update mixer flag */
4073 /* we send a retrieve to that endpoint */
4074 // mixer will update the hold-state of the call and send it to the endpoints is changes
4078 /* check if we have an external call
4079 * this is used to check for encryption ability
4081 int EndpointAppPBX::check_external(char **errstr, class Port **port)
4083 struct call_relation *relation;
4085 class CallPBX *callpbx;
4086 class Endpoint *epoint;
4088 /* some paranoia check */
4089 if (!ea_endpoint->ep_portlist)
4091 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we have no port.\n", ea_endpoint->ep_serial);
4092 *errstr = "No Call";
4095 if (!e_ext.number[0])
4097 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we are not internal extension.\n", ea_endpoint->ep_serial);
4098 *errstr = "No Call";
4102 /* check if we have a call with 2 parties */
4103 call = find_call_id(ea_endpoint->ep_call_id);
4106 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have currently no call.\n", ea_endpoint->ep_serial);
4107 *errstr = "No Call";
4110 if (call->c_type != CALL_TYPE_PBX)
4112 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call is nto a pbx call.\n", ea_endpoint->ep_serial);
4113 *errstr = "No PBX Call";
4116 callpbx = (class CallPBX *)call;
4117 relation = callpbx->c_relation;
4120 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call has no relation.\n", ea_endpoint->ep_serial);
4121 *errstr = "No Call";
4124 if (!relation->next)
4126 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call has no 2nd relation.\n", ea_endpoint->ep_serial);
4127 *errstr = "No Call";
4130 if (relation->next->next)
4132 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call has more than two relations.\n", ea_endpoint->ep_serial);
4133 *errstr = "Err: Conference";
4136 if (relation->epoint_id == ea_endpoint->ep_serial)
4138 relation = relation->next;
4139 if (relation->epoint_id == ea_endpoint->ep_serial)
4141 PERROR("EPOINT(%d) SOFTWARE ERROR: both call relations are related to our endpoint.\n", ea_endpoint->ep_serial);
4142 *errstr = "Software Error";
4147 /* check remote port for external call */
4148 epoint = find_epoint_id(relation->epoint_id);
4151 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call has no 2nd endpoint.\n", ea_endpoint->ep_serial);
4152 *errstr = "No Call";
4155 if (!epoint->ep_portlist)
4157 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not port.\n", ea_endpoint->ep_serial);
4158 *errstr = "No Call";
4161 *port = find_port_id(epoint->ep_portlist->port_id);
4164 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has an none existing port.\n", ea_endpoint->ep_serial);
4165 *errstr = "No Call";
4168 if (((*port)->p_type&PORT_CLASS_mISDN_MASK)!=PORT_CLASS_mISDN_DSS1) /* port is not external isdn */
4170 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not an external port.\n", ea_endpoint->ep_serial);
4171 *errstr = "No Ext Call";
4174 if ((*port)->p_state != PORT_STATE_CONNECT)
4176 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint's port is not in connected state.\n", ea_endpoint->ep_serial);
4177 *errstr = "No Ext Connect";
4183 void EndpointAppPBX::logmessage(struct message *message)
4187 char *logtext = "unknown";
4190 if (message->flow != EPOINT_TO_PORT)
4192 PERROR("EPOINT(%d) message not of correct flow type-\n", ea_endpoint->ep_serial);
4196 switch(message->type)
4199 port = find_port_id(message->id_to);
4202 if (port->p_type == PORT_TYPE_DSS1_NT_OUT)
4204 pdss1 = (class Pdss1 *)port;
4205 printlog("%3d outgoing SETUP from %s='%s'%s%s%s%s to intern='%s' port='%d' (NT)\n",
4206 ea_endpoint->ep_serial,
4207 (message->param.setup.callerinfo.intern[0])?"intern":"extern",
4208 (message->param.setup.callerinfo.intern[0])?e_callerinfo.intern:e_callerinfo.id,
4209 (message->param.setup.callerinfo.present==INFO_PRESENT_RESTRICTED)?" anonymous":"",
4210 (message->param.setup.redirinfo.id[0])?"redirected='":"",
4211 message->param.setup.redirinfo.id,
4212 (message->param.setup.redirinfo.id[0])?"'":"",
4213 message->param.setup.dialinginfo.number,
4214 pdss1->p_m_mISDNport->portnum
4217 if (port->p_type == PORT_TYPE_DSS1_TE_OUT)
4219 pdss1 = (class Pdss1 *)port;
4220 printlog("%3d outgoing SETUP from %s='%s'%s%s%s%s to extern='%s' port='%d' (TE)\n",
4221 ea_endpoint->ep_serial,
4222 (message->param.setup.callerinfo.intern[0])?"intern":"extern",
4223 (message->param.setup.callerinfo.intern[0])?e_callerinfo.intern:e_callerinfo.id,
4224 (message->param.setup.callerinfo.present==INFO_PRESENT_RESTRICTED)?" anonymous":"",
4225 (message->param.setup.redirinfo.id[0])?"redirected='":"",
4226 message->param.setup.redirinfo.id,
4227 (message->param.setup.redirinfo.id[0])?"'":"",
4228 message->param.setup.dialinginfo.number,
4229 pdss1->p_m_mISDNport->portnum
4232 if (port->p_type == PORT_TYPE_VBOX_OUT)
4234 printlog("%3d outgoing SETUP from %s='%s'%s%s%s%s to vbox='%s'\n",
4235 ea_endpoint->ep_serial,
4236 (message->param.setup.callerinfo.intern[0])?"intern":"extern",
4237 (message->param.setup.callerinfo.intern[0])?e_callerinfo.intern:e_callerinfo.id,
4238 (message->param.setup.callerinfo.present==INFO_PRESENT_RESTRICTED)?" anonymous":"",
4239 (message->param.setup.redirinfo.id[0])?"redirected='":"",
4240 message->param.setup.redirinfo.id,
4241 (message->param.setup.redirinfo.id[0])?"'":"",
4242 message->param.setup.dialinginfo.number
4247 case MESSAGE_OVERLAP:
4248 printlog("%3d outgoing SETUP ACKNOWLEDGE\n",
4249 ea_endpoint->ep_serial
4253 case MESSAGE_PROCEEDING:
4254 printlog("%3d outgoing PROCEEDING\n",
4255 ea_endpoint->ep_serial
4259 case MESSAGE_ALERTING:
4260 printlog("%3d outgoing ALERTING\n",
4261 ea_endpoint->ep_serial
4265 case MESSAGE_CONNECT:
4266 printlog("%3d outgoing CONNECT id='%s'%s\n",
4267 ea_endpoint->ep_serial,
4268 message->param.connectinfo.id,
4269 (message->param.connectinfo.present==INFO_PRESENT_RESTRICTED)?" anonymous":""
4273 case MESSAGE_DISCONNECT:
4274 printlog("%3d outgoing DISCONNECT cause='%d' (%s) location='%d' (%s) display='%s'\n",
4275 ea_endpoint->ep_serial,
4276 message->param.disconnectinfo.cause,
4277 (message->param.disconnectinfo.cause>0 && message->param.disconnectinfo.cause<128)?isdn_cause[message->param.disconnectinfo.cause].english:"-",
4278 message->param.disconnectinfo.location,
4279 (message->param.disconnectinfo.location>=0 && message->param.disconnectinfo.location<16)?isdn_location[message->param.disconnectinfo.location].english:"-",
4280 message->param.disconnectinfo.display
4284 case MESSAGE_RELEASE:
4285 printlog("%3d outgoing RELEASE cause='%d' (%s) location='%d' (%s)\n",
4286 ea_endpoint->ep_serial,
4287 message->param.disconnectinfo.cause,
4288 (message->param.disconnectinfo.cause>0 && message->param.disconnectinfo.cause<128)?isdn_cause[message->param.disconnectinfo.cause].english:"-",
4289 message->param.disconnectinfo.location,
4290 (message->param.disconnectinfo.location>=0 && message->param.disconnectinfo.location<16)?isdn_location[message->param.disconnectinfo.location].english:"-"
4294 case MESSAGE_NOTIFY:
4295 switch(message->param.notifyinfo.notify)
4301 logtext = "USER_SUSPENDED";
4304 logtext = "BEARER_SERVICE_CHANGED";
4307 logtext = "USER_RESUMED";
4310 logtext = "CONFERENCE_ESTABLISHED";
4313 logtext = "CONFERENCE_DISCONNECTED";
4316 logtext = "OTHER_PARTY_ADDED";
4319 logtext = "ISOLATED";
4322 logtext = "REATTACHED";
4325 logtext = "OTHER_PARTY_ISOLATED";
4328 logtext = "OTHER_PARTY_REATTACHED";
4331 logtext = "OTHER_PARTY_SPLIT";
4334 logtext = "OTHER_PARTY_DISCONNECTED";
4337 logtext = "CONFERENCE_FLOATING";
4340 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
4343 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
4346 logtext = "CALL_IS_A_WAITING_CALL";
4349 logtext = "DIVERSION_ACTIVATED";
4352 logtext = "RESERVED_CT_1";
4355 logtext = "RESERVED_CT_2";
4358 logtext = "REVERSE_CHARGING";
4361 logtext = "REMOTE_HOLD";
4364 logtext = "REMOTE_RETRIEVAL";
4367 logtext = "CALL_IS_DIVERTING";
4370 SPRINT(buffer, "indicator=%d", message->param.notifyinfo.notify - 0x80);
4374 printlog("%3d outgoing NOTIFY notify='%s' id='%s'%s display='%s'\n",
4375 ea_endpoint->ep_serial,
4377 message->param.notifyinfo.id,
4378 (message->param.notifyinfo.present==INFO_PRESENT_RESTRICTED)?" anonymous":"",
4379 message->param.notifyinfo.display
4383 case MESSAGE_INFORMATION:
4384 printlog("%3d outgoing INFORMATION information='%s'\n",
4385 ea_endpoint->ep_serial,
4386 message->param.information.number
4390 case MESSAGE_FACILITY:
4391 printlog("%3d outgoing FACILITY len='%d'\n",
4392 ea_endpoint->ep_serial,
4393 message->param.facilityinfo.len
4398 printlog("%3d outgoing TONE dir='%s' name='%s'\n",
4399 ea_endpoint->ep_serial,
4400 message->param.tone.dir,
4401 message->param.tone.name
4406 PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message->type);
4410 void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cause, int location, char *display)
4412 struct message *message;
4416 if (!portlist->port_id)
4419 if (!e_connectedmode)
4421 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT);
4422 message->param.disconnectinfo.cause = cause;
4423 message->param.disconnectinfo.location = location;
4425 SCPY(message->param.disconnectinfo.display, display);
4427 SCPY(message->param.disconnectinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4430 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
4432 SCPY(message->param.notifyinfo.display, display);
4434 SCPY(message->param.notifyinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4436 message_put(message);
4437 logmessage(message);