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;
46 e_terminal_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");
140 /* set new endpoint state
142 void EndpointAppPBX::new_state(int state)
144 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new state %s --> %s\n", ea_endpoint->ep_serial, state_name[e_state], state_name[state]);
150 * out==0: incomming caller id, out==1: outgoing caller id
152 void EndpointAppPBX::screen(int out, char *id, int idsize, int *type, int *present)
154 struct interface *interface;
156 interface = interface_first;
159 if (!strcmp(e_callerinfo.interface, interface->name))
163 interface = interface->next;
168 /* screen incoming caller id */
171 /* check for MSN numbers, use first MSN if no match */
173 ifmsn = interface->ifmsn;
178 if (!strcmp(ifmns->mns, id))
184 if (!ifmns && mns1) // not in list, first msn given
185 UNCPY(id, msn1, idsize);
189 /* check screen list */
191 iscreen = interface->ifscreen_out;
193 iscreen = interface->ifscreen_in;
196 if (ifcreen->match_type==-1 || ifscreen->match_type==*type)
197 if (ifcreen->match_present==-1 || ifscreen->match_present==*present)
199 if (strchr(ifcreen->match_id,'%'))
201 if (!strncmp(ifscreen->match_id, id, strchr(ifscreen->match_id,'%')-ifscreen->match_id))
205 if (!strcmp(ifscreen->match_id, id))
209 ifscreen = ifscreen->next;
211 if (ifscreen) // match
213 if (ifscren->result_type != -1)
214 *type = ifscreen->result_type;
215 if (ifscren->result_present != -1)
216 *present = ifscreen->result_present;
217 if (strchr(ifscreen->match_id,'%'))
219 SCPY(suffix, strchr(ifscreen->match_id,'%') - ifscreen->match_id + id);
220 UNCPY(id, ifscreen->result_id);
222 if (strchr(ifscreen->result_id,'%'))
224 *strchr(ifscreen->result_id,'%') = '\0';
225 UNCAT(id, suffix, idsize);
230 UNCPY(id, ifscreen->result_id, idsize);
237 /* release call and port (as specified)
239 void EndpointAppPBX::release(int release, int calllocation, int callcause, int portlocation, int portcause)
241 struct port_list *portlist;
242 struct message *message;
246 /* message to test call */
247 admin_call_response(e_adminid, ADMIN_CALL_RELEASE, "", callcause, calllocation, 0);
249 /* if a release is pending */
250 if (release==RELEASE_CALL || release==RELEASE_ALL || release==RELEASE_PORT_CALLONLY)
252 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): do pending release (callcause %d location %d)\n", ea_endpoint->ep_serial, callcause, calllocation);
253 if (ea_endpoint->ep_call_id)
255 call = find_call_id(ea_endpoint->ep_call_id);
257 call->release(ea_endpoint->ep_serial, 0, calllocation, callcause);
259 ea_endpoint->ep_call_id = 0;
262 if (release != RELEASE_PORT_CALLONLY)
265 call_release(e_hold_id, ea_endpoint->ep_serial, 1, calllocation, callcause);
270 if (release==RELEASE_ALL || release==RELEASE_PORT_CALLONLY)
272 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release (portcause %d portlocation)\n", ea_endpoint->ep_serial, portcause, portlocation);
273 while((portlist = ea_endpoint->ep_portlist))
275 if (portlist->port_id)
277 SPRINT(cause, "cause_%02x", portcause);
278 set_tone(portlist, cause);
279 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
280 message->param.disconnectinfo.cause = portcause;
281 message->param.disconnectinfo.location = portlocation;
282 message_put(message);
285 ea_endpoint->free_portlist(portlist);
288 /* if callback is enabled, call back with the given caller id */
291 /* reset some stuff */
292 new_state(EPOINT_STATE_IDLE);
293 memset(&e_connectinfo, 0, sizeof(struct connect_info));
294 memset(&e_redirinfo, 0, sizeof(struct redir_info));
295 e_start = e_stop = 0;
296 e_ruleset = ruleset_main;
298 e_rule = e_ruleset->rule_first;
300 e_action_timeout = 0;
302 e_match_to_action = NULL;
304 e_extdialing = e_dialinginfo.number;
311 e_multipoint_cause = CAUSE_NOUSER;
312 e_multipoint_location = LOCATION_PRIVATE_LOCAL;
313 e_dialing_queue[0] = '\0';
315 e_crypt_state = CM_ST_NULL;
316 e_crypt_keyengine_busy = 0;
317 e_crypt_info[0] = '\0';
321 e_tx_state = NOTIFY_STATE_ACTIVE;
322 e_rx_state = NOTIFY_STATE_ACTIVE;
323 e_call_cause = e_call_location = 0;
325 /* the caller info of the callback user */
326 memcpy(&e_callbackinfo, &e_callerinfo, sizeof(e_callbackinfo));
327 memset(&e_dialinginfo, 0, sizeof(e_dialinginfo));
328 /* create dialing by callerinfo */
329 if (e_terminal[0] && e_terminal_interface[0])
331 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to internal: %s interface %s\n", ea_endpoint->ep_serial, e_terminal, e_terminal_interface);
332 /* create callback to the current terminal */
333 SCPY(e_dialinginfo.number, e_terminal);
334 SCPY(e_dialinginfo.interfaces, e_terminal_interface);
335 e_dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
336 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
341 SCPY(e_dialinginfo.number, e_cbto);
344 /* numberrize caller id and use it to dial to the callback */
345 SCPY(e_dialinginfo.number, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype));
347 e_dialinginfo.itype = INFO_ITYPE_ISDN;
348 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
349 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to external: %s\n", ea_endpoint->ep_serial, e_dialinginfo.number);
354 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release of epoint itself.\n", ea_endpoint->ep_serial);
355 ea_endpoint->ep_use--; /* when e_lock is 0, the endpoint will be deleted */
361 /* cancel callerid if restricted, unless anon-ignore is enabled at extension or port is of type external (so called police gets caller id :)*/
362 void apply_callerid_restriction(int anon_ignore, int port_type, char *id, int *ntype, int *present, int *screen, char *voip, char *intern, char *name)
364 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");
366 /* caller id is not restricted, so we do nothing */
367 if (*present != INFO_PRESENT_RESTRICTED)
370 /* only extensions are restricted */
376 /* if we enabled anonymouse ignore */
380 /* else we remove the caller id */
384 *ntype = INFO_NTYPE_UNKNOWN;
386 // *screen = INFO_SCREEN_USER;
387 // maybe we should not make voip address anonymous
390 // maybe it's no fraud to present internal id
397 /* used display message to display callerid as available */
398 char *EndpointAppPBX::apply_callerid_display(char *id, int itype, int ntype, int present, int screen, char *voip, char *intern, char *name)
400 static char display[81];
403 char *cid = numberrize_callerinfo(id, ntype);
405 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");
416 /* NOTE: is caller is is not available for this extesion, it has been removed by apply_callerid_restriction already */
418 /* internal extension's caller id */
419 if (intern[0] && e_ext.display_int)
422 SCAT(display, intern);
425 if (itype == INFO_ITYPE_VBOX)
426 SCAT(display, "(vbox)");
428 SCAT(display, "(int)");
431 /* external caller id */
432 if (!intern[0] && !voip[0] && e_ext.display_ext)
438 if (present == INFO_PRESENT_RESTRICTED)
439 SCAT(display, "anonymous");
441 SCAT(display, "unknown");
449 if (voip[0] && e_ext.display_voip)
451 if (!display[0] && cid[0])
458 /* display if callerid is anonymouse but available due anon-ignore */
459 if (e_ext.display_anon && present==INFO_PRESENT_RESTRICTED)
462 SCAT(display, "unknown");
465 SCAT(display, " anon");
468 /* display if callerid is anonymouse but available due anon-ignore */
469 if (e_ext.display_fake && screen==INFO_SCREEN_USER && present!=INFO_PRESENT_NULL)
475 if (present == INFO_PRESENT_RESTRICTED)
476 SCAT(display, "anonymous");
478 SCAT(display, "unknown");
483 SCAT(display, " fake");
487 if (name[0] && e_ext.display_name)
489 if (!display[0] && cid[0])
500 * uses the current state to notify activity
502 void EndpointAppPBX::notify_active(void)
504 struct port_list *portlist = ea_endpoint->ep_portlist;
505 struct message *message;
510 case NOTIFY_STATE_ACTIVE:
511 /* we are already active, so we don't do anything */
514 case NOTIFY_STATE_SUSPEND:
515 notify = INFO_NOTIFY_USER_RESUMED;
518 set_tone(portlist, NULL);
519 portlist = portlist->next;
521 portlist = ea_endpoint->ep_portlist;
524 case NOTIFY_STATE_HOLD:
525 notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
528 set_tone(portlist, NULL);
529 portlist = portlist->next;
531 portlist = ea_endpoint->ep_portlist;
534 case NOTIFY_STATE_CONFERENCE:
535 notify = INFO_NOTIFY_CONFERENCE_DISCONNECTED;
538 set_tone(portlist, NULL);
539 portlist = portlist->next;
541 portlist = ea_endpoint->ep_portlist;
545 PERROR("unknown e_tx_state = %d\n", e_tx_state);
551 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
552 message->param.notifyinfo.notify = notify;
553 message_put(message);
555 portlist = portlist->next;
561 * keypad functions during call. one example to use this is to put a call on hold or start a conference
563 void EndpointAppPBX::keypad_function(char digit)
566 /* we must be in a call, in order to send messages to the call */
567 if (e_terminal[0] == '\0')
569 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) IGNORING keypad received not from extension.\n", ea_endpoint->ep_serial);
575 /* join conference */
577 if (ea_endpoint->ep_call_id == 0)
579 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad received during connect but not during a call.\n", ea_endpoint->ep_serial);
582 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join call with call on hold\n", ea_endpoint->ep_serial);
588 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) shared key encryption selected.\n", ea_endpoint->ep_serial);
592 /* crypt key-exchange */
594 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) key exchange encryption selected.\n", ea_endpoint->ep_serial);
600 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) encryption off selected.\n", ea_endpoint->ep_serial);
605 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) unsupported keypad digit '%c'.\n", ea_endpoint->ep_serial, digit);
610 /* set tone pattern for port */
611 void EndpointAppPBX::set_tone(struct port_list *portlist, char *tone)
613 struct message *message;
618 /* store for suspended processes */
623 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no endpoint to notify tone.\n", ea_endpoint->ep_serial);
627 if (e_call_pattern /* pattern are provided */
628 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_SETUP)
629 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_OVERLAP)
630 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_IN_PROCEEDING)
631 && !(e_ext.own_alerting && e_state == EPOINT_STATE_IN_ALERTING)
632 && !(e_ext.own_cause && e_state == EPOINT_STATE_IN_DISCONNECT)
633 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_SETUP)
634 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_OVERLAP)
635 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_OUT_PROCEEDING)
636 && !(e_ext.own_alerting && e_state == EPOINT_STATE_OUT_ALERTING)
637 && !(e_ext.own_cause && e_state == EPOINT_STATE_OUT_DISCONNECT)
638 && tone[0] && !!strncmp(tone,"crypt_*",6))
640 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) tone not provided since patterns are available\n", ea_endpoint->ep_serial);
646 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_TONE);
647 SCPY(message->param.tone.dir, e_ext.tones_dir[0]?e_ext.tones_dir:options.tones_dir);
648 SCPY(message->param.tone.name, tone);
649 message_put(message);
656 * hunts an mISDNport that is available for an outgoing call
657 * if no ifname was given, any interface that is not an extension
660 static struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel)
662 struct interface *interface;
663 struct mISDNport *mISDNport;
665 interface = interface_first;
667 /* first find the given interface or, if not given, one with no extension */
672 /* check for given interface */
675 if (!strcasecmp(interface->name, ifname))
677 /* found explicit interface */
678 printlog("%3d interface %s found as given\n", ea_endpoint->ep_serial, ifname);
684 if (!interface->extension)
686 /* found non extension */
687 printlog("%3d interface %s found, that is not an extension\n", ea_endpoint->ep_serial, interface->name);
692 interface = interface->next;
695 /* see if interface has ports */
696 if (!interface->ifport)
699 printlog("%3d interface %s has no active ports, skipping.\n", ea_endpoint->ep_serial, interface->name);
700 interface = interface->next;
704 /* select port by algorithm */
705 ifport_start = interface->port;
707 if (interface->hunt == HUNT_ROUNDROBIN)
709 while(ifport_start->next && index<interface->hunt_next)
711 ifport_start = ifport_start->next;
714 printlog("%3d starting with port#%d position %d (round-robin)\n", ea_endpoint->ep_serial, ifport_start->portnum, index);
718 ifport = ifport_start;
721 /* see if port is available */
722 if (!ifport->mISDNport)
724 printlog("%3d port#%d position %d is not available, skipping.\n", ea_endpoint->ep_serial, ifport->portnum, index);
727 mISDNport = ifport->mISDNport;
729 #warning admin block auch bei incomming calls
730 #warning calls releasen, wenn port entfernt wird, geblockt wird
731 /* see if port is administratively blocked */
734 printlog("%3d port#%d position %d is administratively blocked, skipping.\n", ea_endpoint->ep_serial, ifport->portnum, index);
738 /* see if link is up */
739 if (mISDNport->ptp && !mISDNport->l2link)
741 printlog("%3d port#%d position %d is ptp but layer 2 is down.\n", ea_endpoint->ep_serial, ifport->portnum, index);
742 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) skipping because it is PTP with L2 down\n", ea_endpoint->ep_serial);
746 /* check for channel form selection list */
748 selchannel = ifport->selchannel;
751 switch(selchannel->channel)
753 case CHANNEL_FREE: /* free channel */
754 if (mISDNport->b_inuse >= mISDNport->b_num)
755 break; /* all channel in use or reserverd */
758 while(i < mISDNport->b_num)
760 if (mISDNport->b_port[i] == NULL)
762 *channel = i+1+(i>=15);
763 printlog("%3d port#%d position %d selecting free channel %d\n", ea_endpoint->ep_serial, ifport->portnum, index, *channel);
770 case CHANNEL_ANY: /* don't ask for channel */
771 if (mISDNport->b_inuse >= mISDNport->b_num)
773 break; /* all channel in use or reserverd */
775 printlog("%3d port#%d position %d using with 'any channel'\n", ea_endpoint->ep_serial, ifport->portnum, index);
776 *channel = SEL_CHANNEL_ANY;
779 case CHANNEL_NO: /* call waiting */
780 printlog("%3d port#%d position %d using with 'no channel'\n", ea_endpoint->ep_serial, ifport->portnum, index);
781 *channel = SEL_CHANNEL_NO;
785 if (selchannel->channel<1 || selchannel->channel==16)
786 break; /* invalid channels */
787 i = selchannel->channel-1-(selchannel->channel>=17);
788 if (i >= mISDNport->b_num)
789 break; /* channel not in port */
790 if (mISDNport->b_port[i] == NULL)
792 *channel = selchannel->channel;
793 printlog("%3d port#%d position %d selecting given channel %d\n", ea_endpoint->ep_serial, ifport->portnum, index, *channel);
799 break; /* found channel */
800 selchannel = selchannel->next;
803 /* if channel was found, return mISDNport and channel */
806 /* setting next port to start next time */
807 if (interface->hunt == HUNT_ROUNDROBIN)
812 interface->hunt_next = index;
818 printlog("%3d port#%d position %d skipping, because no channel found.\n", ea_endpoint->ep_serial, ifport->portnum, index);
821 /* go next port, until all ports are checked */
823 ifport = ifport->next;
827 ifport = interface->ifport;
829 if (ifport != ifport_start)
832 return(NULL); /* no port found */
835 /* outgoing setup to port(s)
836 * ports will be created and a setup is sent if everything is ok. otherwhise
837 * the endpoint is destroyed.
839 void EndpointAppPBX::out_setup(void)
841 struct dialing_info dialinginfo;
843 // class pdss1 *pdss1;
844 struct port_list *portlist;
845 struct message *message;
847 int cause = CAUSE_RESSOURCEUNAVAIL;
850 struct mISDNport *mISDNport;
853 class EndpointAppPBX *atemp;
854 // char allowed_ports[256];
858 char ifname[sizeof(e_ext.interfaces)],
860 struct port_settings port_settings;
863 /* create settings for creating port */
864 memset(&port_settings, 0, sizeof(port_settings));
866 SCPY(port_settings.tones_dir, e_ext.tones_dir);
868 SCPY(port_settings.tones_dir, options.tones_dir);
869 port_settings.tout_setup = e_ext.tout_setup;
870 port_settings.tout_dialing = e_ext.tout_dialing;
871 port_settings.tout_proceeding = e_ext.tout_proceeding;
872 port_settings.tout_alerting = e_ext.tout_alerting;
873 port_settings.tout_disconnect = e_ext.tout_disconnect;
874 // port_settings.tout_hold = e_ext.tout_hold;
875 // port_settings.tout_park = e_ext.tout_park;
876 port_settings.no_seconds = e_ext.no_seconds;
878 /* 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 */
880 /* check what dialinginfo.itype we got */
881 switch(e_dialinginfo.itype)
883 /* *********************** call to extension or vbox */
884 case INFO_ITYPE_ISDN_EXTENSION:
885 /* check if we deny incoming calls when we use an extension */
886 if (e_ext.noknocking)
888 atemp = apppbx_first;
892 if (!strcmp(atemp->e_terminal, e_terminal))
898 PERROR("EPOINT(%d) noknocking and currently a call\n", ea_endpoint->ep_serial);
899 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYSPE_ call, port */
900 return; /* must exit here */
903 /* FALL THROUGH !!!! */
904 case INFO_ITYPE_VBOX:
905 /* get dialed extension's info */
906 // SCPY(exten, e_dialinginfo.number);
907 // if (strchr(exten, ','))
908 // *strchr(exten, ',') = '\0';
909 // if (!read_extension(&e_ext, exten))
910 if (!read_extension(&e_ext, e_dialinginfo.number))
912 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) extension %s not configured\n", ea_endpoint->ep_serial, e_dialinginfo.number);
913 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
914 return; /* must exit here */
917 if (e_dialinginfo.itype == INFO_ITYPE_VBOX)
919 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing directly to VBOX\n", ea_endpoint->ep_serial);
924 /* string from unconditional call forward (cfu) */
928 /* present to forwarded party */
929 if (e_ext.anon_ignore && e_callerinfo.id[0])
931 e_callerinfo.present = INFO_PRESENT_ALLOWED;
933 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
937 /* string from busy call forward (cfb) */
941 class EndpointAppPBX *checkapp = apppbx_first;
944 if (checkapp != this) /* any other endpoint except our own */
946 if (!strcmp(checkapp->e_terminal, e_terminal))
948 /* present to forwarded party */
949 if (e_ext.anon_ignore && e_callerinfo.id[0])
951 e_callerinfo.present = INFO_PRESENT_ALLOWED;
953 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
957 checkapp = checkapp->next;
961 /* string from no-response call forward (cfnr) */
965 /* when cfnr is done, out_setup() will setup the call */
968 /* present to forwarded party */
969 if (e_ext.anon_ignore && e_callerinfo.id[0])
971 e_callerinfo.present = INFO_PRESENT_ALLOWED;
975 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
977 e_cfnr_release = now + e_ext.cfnr_delay;
978 e_cfnr_call = now + e_ext.cfnr_delay + 1; /* call one second after release */
979 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);
983 /* call to all internal interfaces */
984 p = e_ext.interfaces;
985 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) generating multiple calls for extension %s to interfaces %s\n", ea_endpoint->ep_serial, e_dialinginfo.number, p);
989 while(*p!=',' && *p!='\0')
994 /* found interface */
995 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
996 /* hunt for mISDNport and create Port */
997 mISDNport = hunt_port(ifname, &channel);
1000 printlog("%3d endpoint INTERFACE '%s' not found or busy\n", ea_endpoint->ep_serial, ifname);
1001 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) given interface: '%s' not found or too busy to accept calls.\n", ea_endpoint->ep_serial, e_ext.interfaces);
1004 /* creating INTERNAL port */
1005 SPRINT(portname, "%s-%d-out", mISDNport->interface_name, mISDNport->portnum);
1006 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport.channel_force);
1009 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port '%s' failed to create\n", ea_endpoint->ep_serial, mISDNport->interface_name);
1010 goto check_anycall_intern;
1012 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
1013 memset(&dialinginfo, 0, sizeof(dialinginfo));
1014 SCPY(dialinginfo.number, e_dialinginfo.number);
1015 dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
1016 dialinginfo.ntype = e_dialinginfo.ntype;
1017 /* create port_list relation */
1018 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->is_earlyb);
1021 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1023 goto check_anycall_intern;
1025 /* directory.list */
1026 if (e_callerinfo.id[0] && (e_ext.centrex || e_ext.display_name))
1028 dirname = parse_directory(e_callerinfo.id, e_callerinfo.ntype);
1030 SCPY(e_callerinfo.name, dirname);
1032 // dss1 = (class Pdss1 *)port;
1034 //printf("INTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.number);
1035 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1036 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1037 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1038 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1039 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1040 //terminal SCPY(message->param.setup.from_terminal, e_terminal);
1041 //terminal if (e_dialinginfo.number)
1042 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.number);
1043 /* handle restricted caller ids */
1044 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);
1045 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);
1046 /* display callerid if desired for extension */
1047 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));
1048 //printf("\n\ndisplay = %s\n\n\n",message->param.setup.callerinfo.display);
1049 /* use cnip, if enabld */
1051 message->param.setup.callerinfo.name[0] = '\0';
1052 /* screen clip if prefix is required */
1053 if (message->param.setup.callerinfo.id[0] && e_ext.clip_prefix[0])
1055 SCPY(message->param.setup.callerinfo.id, e_ext.clip_prefix);
1056 SCAT(message->param.setup.callerinfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype));
1057 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1059 /* use internal caller id */
1060 if (e_callerinfo.intern[0] && (message->param.setup.callerinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
1062 SCPY(message->param.setup.callerinfo.id, e_callerinfo.intern);
1063 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1065 message_put(message);
1066 logmessage(message);
1070 /* string from parallel call forward (cfp) */
1074 if (e_ext.anon_ignore && e_callerinfo.id[0])
1076 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1080 vbox_only: /* entry point for answering machine only */
1081 cfu_only: /* entry point for cfu */
1082 cfb_only: /* entry point for cfb */
1083 cfnr_only: /* entry point for cfnr */
1084 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call extension %s for external destiantion(s) '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.number, p);
1088 /* only if vbox should be dialed, and terminal is given */
1090 if (!strcmp(p, "vbox") && e_terminal[0])
1092 /* go to the end of p */
1095 /* answering vbox call */
1096 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) answering machine\n", ea_endpoint->ep_serial);
1098 if (!(port = new VBoxPort(PORT_TYPE_VBOX_OUT, &port_settings)))
1100 PERROR("EPOINT(%d) no mem for port\n", ea_endpoint->ep_serial);
1103 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocated port %s\n", ea_endpoint->ep_serial, port->p_name);
1104 UCPY(cfp, e_terminal); /* cfp or any other direct forward/vbox */
1108 while(*p!=',' && *p!='\0')
1114 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cfp external %s\n", ea_endpoint->ep_serial, cfp);
1115 /* hunt for mISDNport and create Port */
1116 mISDNport = mISDNport_first;
1120 /* check for external or given interface */
1121 if (((!e_dialinginfo.interfaces[0])&&mISDNport->iftype==IF_EXTERN) || !strcmp(mISDNport->interface_name, e_dialinginfo.interfaces))
1123 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) interface '%s' found\n", ea_endpoint->ep_serial, mISDNport->interface_name);
1124 cause = CAUSE_NOCHANNEL; /* when failing: out of channels */
1125 /* if PTP, skip all down links */
1126 if (mISDNport->ptp && !mISDNport->l2link)
1128 printlog("%3d endpoint INTERFACE Layer 2 of interface '%s' is down.\n", ea_endpoint->ep_serial, mISDNport->interface_name);
1129 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) skipping because it is PTP with L2 down\n", ea_endpoint->ep_serial);
1130 mISDNport = mISDNport->next;
1133 /* if no channel is available */
1134 if (mISDNport->multilink || !mISDNport->ntmode || mISDNport->ptp)
1138 ii = mISDNport->b_num;
1141 if (mISDNport->b_state[i])
1145 if (use >= mISDNport->b_num)
1147 printlog("%3d endpoint INTERFACE Interface '%s' has no free channel.\n", ea_endpoint->ep_serial, mISDNport->interface_name);
1148 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);
1149 mISDNport = mISDNport->next;
1153 /* found interface */
1154 printlog("%3d endpoint INTERFACE Interface '%s' found for external call.\n", ea_endpoint->ep_serial, mISDNport->interface_name);
1157 mISDNport = mISDNport->next;
1161 /* creating EXTERNAL port*/
1162 SPRINT(portname, "%s-%d-out", mISDNport->interface_name, mISDNport->portnum);
1163 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings);
1164 earlyb = mISDNport->is_earlyb;
1168 printlog("%3d endpoint INTERFACE External interface not found or busy.\n", ea_endpoint->ep_serial);
1169 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");
1174 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port found or created, which is idle.\n", ea_endpoint->ep_serial);
1175 goto check_anycall_intern;
1177 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found or created port %s\n", ea_endpoint->ep_serial, port->p_name);
1178 memset(&dialinginfo, 0, sizeof(dialinginfo));
1179 SCPY(dialinginfo.number, cfp);
1180 dialinginfo.itype = INFO_ITYPE_EXTERN;
1181 dialinginfo.ntype = e_dialinginfo.ntype;
1182 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
1185 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1187 goto check_anycall_intern;
1189 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.number);
1190 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1191 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1192 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1193 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1194 /* if clip is hidden */
1195 if (e_ext.clip==CLIP_HIDE && port->p_type!=PORT_TYPE_VBOX_OUT)
1197 SCPY(message->param.setup.callerinfo.id, e_ext.callerid);
1198 SCPY(message->param.setup.callerinfo.intern, e_terminal);
1199 message->param.setup.callerinfo.ntype = e_ext.callerid_type;
1200 message->param.setup.callerinfo.present = e_ext.callerid_present;
1202 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1203 //terminal SCPY(message->param.setup.from_terminal, e_terminal);
1204 //terminal if (e_dialinginfo.number)
1205 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.number);
1206 /* handle restricted caller ids */
1207 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);
1208 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);
1209 /* display callerid if desired for extension */
1210 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));
1211 message_put(message);
1212 logmessage(message);
1216 check_anycall_intern:
1217 /* now we have all ports created */
1220 printlog("%3d endpoint INTERFACE No port or no parallel forwarding defined. Nothing to call to.\n", ea_endpoint->ep_serial);
1221 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port or no cfp defined for extension, nothing to dial.\n", ea_endpoint->ep_serial);
1222 if (!ea_endpoint->ep_call_id)
1224 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
1225 return; /* must exit here */
1229 /* *********************** external call */
1231 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.number);
1232 /* call to extenal interfaces */
1233 p = e_dialinginfo.number;
1237 while(*p!=',' && *p!='\0')
1238 SCCAT(number, *p++);
1242 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");
1243 /* hunt for mISDNport and create Port */
1244 mISDNport = mISDNport_first;
1248 /* check for external or given interface */
1249 if ((!e_dialinginfo.interfaces[0]&&mISDNport->iftype==IF_EXTERN) || !strcmp(mISDNport->interface_name, e_dialinginfo.interfaces))
1251 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) interface '%s' found\n", ea_endpoint->ep_serial, mISDNport->interface_name);
1252 cause = CAUSE_NOCHANNEL; /* when failing: out of channels */
1253 /* if PTP, skip all down links */
1254 if (mISDNport->ptp && !mISDNport->l2link)
1256 printlog("%3d endpoint INTERFACE Layer 2 of interface '%s' is down.\n", ea_endpoint->ep_serial, mISDNport->interface_name);
1257 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) skipping because it is PTP with L2 down\n", ea_endpoint->ep_serial);
1258 mISDNport = mISDNport->next;
1261 /* if no channel is available */
1262 if (mISDNport->multilink || !mISDNport->ntmode || mISDNport->ptp)
1266 ii = mISDNport->b_num;
1269 if (mISDNport->b_state[i])
1273 if (use >= mISDNport->b_num)
1275 printlog("%3d endpoint INTERFACE Interface '%s' has no free channel.\n", ea_endpoint->ep_serial, mISDNport->interface_name);
1276 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);
1277 mISDNport = mISDNport->next;
1281 /* found interface */
1282 printlog("%3d endpoint INTERFACE Interface '%s' found for external call.\n", ea_endpoint->ep_serial, mISDNport->interface_name);
1285 mISDNport = mISDNport->next;
1289 printlog("%3d endpoint INTERFACE External interface not found or busy.\n", ea_endpoint->ep_serial);
1290 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");
1291 goto check_anycall_extern;
1293 /* creating EXTERNAL port*/
1294 SPRINT(portname, "%s-%d-out", mISDNport->interface_name, mISDNport->portnum);
1295 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings);
1298 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no external port available\n", ea_endpoint->ep_serial);
1299 goto check_anycall_extern;
1301 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
1302 memset(&dialinginfo, 0, sizeof(dialinginfo));
1303 SCPY(dialinginfo.number, number);
1304 dialinginfo.itype = INFO_ITYPE_EXTERN;
1305 dialinginfo.ntype = e_dialinginfo.ntype;
1306 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->is_earlyb);
1309 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1311 goto check_anycall_extern;
1313 // dss1 = (class Pdss1 *)port;
1314 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.number);
1315 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1316 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1317 SCPY(message->param.setup.dialinginfo.number, number);
1318 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1319 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1320 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1321 //terminal SCPY(message->param.setup.from_terminal, e_terminal);
1322 //terminal if (e_dialinginfo.number)
1323 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.number);
1324 /* handle restricted caller ids */
1325 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);
1326 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);
1327 /* display callerid if desired for extension */
1328 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));
1329 message_put(message);
1330 logmessage(message);
1334 check_anycall_extern:
1335 /* now we have all ports created */
1338 printlog("%3d endpoint INTERFACE No free port found for making any call.\n", ea_endpoint->ep_serial);
1339 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port found which is idle for at least one number\n", ea_endpoint->ep_serial);
1340 if (!ea_endpoint->ep_call_id)
1342 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
1343 return; /* must exit here */
1351 /* handler for endpoint
1355 int EndpointAppPBX::handler(void)
1357 if (e_crypt_state!=CM_ST_NULL)
1362 /* process answering machine (play) handling */
1365 if (e_action->index == ACTION_VBOX_PLAY)
1368 /* process action timeout */
1369 if (e_action_timeout)
1370 if (now_d >= e_action_timeout)
1372 if (e_state!=EPOINT_STATE_CONNECT)
1375 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current action timed out.\n", ea_endpoint->ep_serial);
1376 e_multipoint_cause = CAUSE_NOUSER;
1377 e_multipoint_location = LOCATION_PRIVATE_LOCAL;
1378 new_state(EPOINT_STATE_IN_OVERLAP);
1381 return(1); /* we must exit, because our endpoint might be gone */
1383 e_action_timeout = 0;
1386 /* process action timeout */
1387 if (e_match_timeout)
1388 if (now_d >= e_match_timeout)
1391 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we got a match timeout.\n", ea_endpoint->ep_serial);
1393 return(1); /* we must exit, because our endpoint might be gone */
1398 /* process redialing (epoint redials to port) */
1401 if (now_d >= e_redial)
1404 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial.\n", ea_endpoint->ep_serial);
1406 new_state(EPOINT_STATE_OUT_SETUP);
1407 /* call special setup routine */
1414 /* process powerdialing (epoint redials to epoint) */
1415 if (e_powerdialing > 0)
1417 if (now_d >= e_powerdialing)
1419 e_powerdialing = -1; /* leave power dialing on */
1420 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial of powerdial.\n", ea_endpoint->ep_serial);
1423 e_ruleset = ruleset_main;
1425 e_rule = e_ruleset->rule_first;
1427 new_state(EPOINT_STATE_IN_OVERLAP);
1433 /* process call forward no response */
1436 struct port_list *portlist;
1437 struct message *message;
1439 if (now >= e_cfnr_release)
1441 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-no-response time has expired, hanging up.\n", ea_endpoint->ep_serial);
1444 /* release all ports */
1445 while((portlist = ea_endpoint->ep_portlist))
1447 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1448 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
1449 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1450 message_put(message);
1451 logmessage(message);
1452 ea_endpoint->free_portlist(portlist);
1455 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
1456 message->param.channel = CHANNEL_STATE_HOLD;
1457 message_put(message);
1458 /* indicate no patterns */
1459 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_NOPATTERN);
1460 message_put(message);
1461 /* set setup state, since we have no response from the new call */
1462 new_state(EPOINT_STATE_OUT_SETUP);
1467 if (now >= e_cfnr_call)
1469 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-busy time has expired, calling the forwarded number: %s.\n", ea_endpoint->ep_serial, e_ext.cfnr);
1475 /* handle connection to user */
1476 if (e_state == EPOINT_STATE_IDLE)
1478 /* epoint is idle, check callback */
1480 if (now_d >= e_callback)
1482 e_callback = 0; /* done with callback */
1483 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting callback.\n", ea_endpoint->ep_serial);
1484 new_state(EPOINT_STATE_OUT_SETUP);
1490 /* check for password timeout */
1492 if (e_action->index==ACTION_PASSWORD || e_action->index==ACTION_PASSWORD_WRITE)
1494 struct port_list *portlist;
1496 if (now >= e_password_timeout)
1498 e_ruleset = ruleset_main;
1500 e_rule = e_ruleset->rule_first;
1502 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) password timeout %s\n", ea_endpoint->ep_serial, e_extdialing);
1503 printlog("%3d endpoint PASSWORD timeout\n", ea_endpoint->ep_serial);
1504 e_connectedmode = 0;
1506 new_state(EPOINT_STATE_OUT_DISCONNECT);
1507 portlist = ea_endpoint->ep_portlist;
1510 message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
1511 set_tone(portlist, "cause_10");
1521 /* doing a hookflash */
1522 void EndpointAppPBX::hookflash(void)
1526 /* be sure that we are active */
1528 e_tx_state = NOTIFY_STATE_ACTIVE;
1530 printlog("%3d endpoint HOOKFLASH\n", ea_endpoint->ep_serial);
1531 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf hookflash detected.\n", ea_endpoint->ep_serial);
1532 if (ea_endpoint->ep_use > 1)
1534 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot hooflash while child process is running.\n", ea_endpoint->ep_serial);
1537 /* dialtone after pressing the hash key */
1538 process_hangup(e_call_cause, e_call_location);
1539 e_multipoint_cause = CAUSE_NOUSER;
1540 e_multipoint_location = LOCATION_PRIVATE_LOCAL;
1541 port = find_port_id(ea_endpoint->ep_portlist->port_id);
1544 port->set_echotest(0);
1546 if (ea_endpoint->ep_call_id)
1548 release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
1550 e_ruleset = ruleset_main;
1552 e_rule = e_ruleset->rule_first;
1554 new_state(EPOINT_STATE_IN_OVERLAP);
1555 e_connectedmode = 1;
1556 SCPY(e_dialinginfo.number, e_ext.prefix);
1557 e_extdialing = e_dialinginfo.number;
1559 if (e_dialinginfo.number[0])
1561 set_tone(ea_endpoint->ep_portlist, "dialing");
1565 set_tone(ea_endpoint->ep_portlist, "dialpbx");
1572 /* messages from port
1574 /* port MESSAGE_SETUP */
1575 void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, union parameter *param)
1577 struct message *message;
1580 char extension1[32];
1582 int writeext; /* flags need to write extension after modification */
1585 portlist->port_type = param->setup.port_type;
1586 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
1587 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
1588 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
1589 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
1590 e_dtmf = param->setup.dtmf;
1592 /* screen by interface */
1593 if (e_callerinfo.interface[0])
1595 /* screen incoming caller id */
1596 screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present);
1598 colp, outclip, outcolp
1600 /* process extension */
1601 if (e_callerinfo.itype == INFO_ITYPE_INTERN)
1603 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is extension\n", ea_endpoint->ep_serial);
1604 /* port makes call from extension */
1605 SCPY(e_callerinfo.intern, e_callerinfo.id);
1606 SCPY(e_terminal, e_callerinfo.intern);
1607 SCPY(e_terminal_interface, e_callerinfo.interface);
1610 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is external or voip\n", ea_endpoint->ep_serial);
1612 printlog("%3d incoming %s='%s'%s%s%s%s dialing='%s'\n",
1613 ea_endpoint->ep_serial,
1614 (e_callerinfo.intern[0])?"SETUP from extension":"SETUP from extern",
1615 (e_callerinfo.intern[0])?e_callerinfo.intern:e_callerinfo.id,
1616 (e_callerinfo.present==INFO_PRESENT_RESTRICTED)?" anonymous":"",
1617 (e_redirinfo.id[0])?"redirected='":"",
1619 (e_redirinfo.id[0])?"'":"",
1620 e_dialinginfo.number
1623 if (e_callerinfo.itype == INFO_ITYPE_INTERN)
1625 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from extension '%s'\n", ea_endpoint->ep_serial, e_terminal);
1627 /* get extension's info about caller */
1628 if (!read_extension(&e_ext, e_terminal))
1630 /* extension doesn't exist */
1631 printlog("%3d endpoint EXTENSION '%s' doesn't exist, please check or create.\n", ea_endpoint->ep_serial, e_callerinfo.id);
1632 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting call from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_terminal);
1633 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
1634 new_state(EPOINT_STATE_OUT_DISCONNECT);
1635 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
1636 e_terminal[0] = '\0'; /* no terminal */
1641 /* put prefix (next) in front of e_dialinginfo.number */
1644 SPRINT(buffer, "%s%s", e_ext.next, e_dialinginfo.number);
1645 SCPY(e_dialinginfo.number, buffer);
1646 e_ext.next[0] = '\0';
1648 } else if (e_ext.prefix[0])
1650 SPRINT(buffer, "%s%s", e_ext.prefix, e_dialinginfo.number);
1651 SCPY(e_dialinginfo.number, buffer);
1654 /* screen caller id */
1655 e_callerinfo.screen = INFO_SCREEN_NETWORK;
1657 SCPY(e_callerinfo.name, e_ext.name);
1658 /* use caller id (or if exist: id_next_call) for this call */
1659 if (e_ext.id_next_call_present >= 0)
1661 SCPY(e_callerinfo.id, e_ext.id_next_call);
1662 /* if we restrict the pesentation */
1663 if (e_ext.id_next_call_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1664 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1665 else e_callerinfo.present = e_ext.id_next_call_present;
1666 e_callerinfo.ntype = e_ext.id_next_call_type;
1667 e_ext.id_next_call_present = -1;
1671 SCPY(e_callerinfo.id, e_ext.callerid);
1672 /* if we restrict the pesentation */
1673 if (e_ext.callerid_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1674 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1675 else e_callerinfo.present = e_ext.callerid_present;
1676 e_callerinfo.ntype = e_ext.callerid_type;
1679 /* extension is written */
1681 write_extension(&e_ext, e_terminal);
1683 /* set volume of rx and tx */
1684 if (param->setup.callerinfo.itype == INFO_ITYPE_INTERN)
1685 if (e_ext.txvol!=256 || e_ext.rxvol!=256)
1687 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
1688 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
1689 message->param.mISDNsignal.rxvol = e_ext.txvol;
1690 message->param.mISDNsignal.txvol = e_ext.rxvol;
1691 message_put(message);
1694 /* start recording if enabled */
1695 if (e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO))
1697 /* check if we are a terminal */
1698 if (e_terminal[0] == '\0')
1699 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
1702 port = find_port_id(portlist->port_id);
1704 port->open_record(e_ext.record, 0, 0, e_terminal, e_ext.anon_ignore, "", 0);
1709 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from external port\n", ea_endpoint->ep_serial);
1710 /* no terminal identification */
1711 e_terminal[0] = '\0';
1712 e_terminal_interface[0] = '\0';
1713 memset(&e_ext, 0, sizeof(e_ext));
1714 e_ext.rights = 4; /* right to dial internat */
1718 e_ruleset = ruleset_main;
1720 e_rule = e_ruleset->rule_first;
1722 e_extdialing = e_dialinginfo.number;
1723 new_state(EPOINT_STATE_IN_SETUP);
1724 if (e_dialinginfo.number[0])
1726 set_tone(portlist, "dialing");
1730 set_tone(portlist, "dialpbx");
1732 set_tone(portlist, "dialtone");
1735 if (e_state == EPOINT_STATE_IN_SETUP)
1737 /* request MORE info, if not already at higher state */
1738 new_state(EPOINT_STATE_IN_OVERLAP);
1739 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_OVERLAP);
1740 message_put(message);
1741 logmessage(message);
1745 /* port MESSAGE_INFORMATION */
1746 void EndpointAppPBX::port_information(struct port_list *portlist, int message_type, union parameter *param)
1748 printlog("%3d incoming INFORMATION information='%s'\n",
1749 ea_endpoint->ep_serial,
1750 param->information.number
1754 /* turn off dtmf detection, in case dtmf is sent with keypad information */
1757 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_terminal, e_callerinfo.id);
1761 /* if vbox_play is done, the information are just used as they come */
1763 if (e_action->index == ACTION_VBOX_PLAY)
1765 /* concat dialing string */
1766 SCAT(e_dialinginfo.number, param->information.number);
1771 /* keypad when disconnect but in connected mode */
1772 if (e_state==EPOINT_STATE_OUT_DISCONNECT && e_connectedmode)
1774 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received after disconnect: %s.\n", ea_endpoint->ep_serial, param->information.number);
1775 /* processing keypad function */
1776 if (param->information.number[0] == '0')
1783 /* keypad when connected */
1784 if (e_state == EPOINT_STATE_CONNECT && e_ext.keypad)
1786 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.number);
1787 /* processing keypad function */
1788 if (param->information.number[0] == '0')
1792 if (param->information.number[0])
1793 keypad_function(param->information.number[0]);
1796 if (e_state != EPOINT_STATE_IN_OVERLAP)
1798 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in overlap, or connect state.\n", ea_endpoint->ep_serial);
1801 if (!param->information.number[0])
1803 if (e_dialinginfo.number[0]=='\0' && !e_action)
1805 set_tone(portlist, "dialing");
1808 if (e_action->index==ACTION_OUTDIAL
1809 || e_action->index==ACTION_EXTERNAL)
1812 set_tone(portlist, "dialing");
1813 else if (!e_extdialing[0])
1814 set_tone(portlist, "dialing");
1816 /* concat dialing string */
1817 SCAT(e_dialinginfo.number, param->information.number);
1821 /* port MESSAGE_DTMF */
1822 void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
1824 printlog("%3d incoming DTMF digit='%c'\n",
1825 ea_endpoint->ep_serial,
1828 /* only if dtmf detection is enabled */
1831 PDEBUG(DEBUG_EPOINT, "dtmf detection is disabled\n");
1836 NOTE: vbox is now handled due to overlap state
1837 /* if vbox_play is done, the dtmf digits are just used as they come */
1839 if (e_action->index == ACTION_VBOX_PLAY)
1841 /* concat dialing string */
1842 if (strlen(e_dialinginfo.number)+1 < sizeof(e_dialinginfo.number))
1844 e_dialinginfo.number[strlen(e_dialinginfo.number)+1] = '\0';
1845 e_dialinginfo.number[strlen(e_dialinginfo.number)] = param->dtmf;
1848 /* continue to process *X# sequences */
1852 /* check for *X# sequence */
1853 if (e_state == EPOINT_STATE_CONNECT)
1855 if (e_dtmf_time+3 < now)
1857 /* the last digit was too far in the past to be a sequence */
1858 if (param->dtmf == '*')
1859 /* only start is allowed in the sequence */
1865 /* we have a sequence of digits, see what we got */
1866 if (param->dtmf == '*')
1868 else if (param->dtmf>='0' && param->dtmf<='9')
1870 /* we need to have a star before we receive the digit of the sequence */
1871 if (e_dtmf_last == '*')
1872 e_dtmf_last = param->dtmf;
1873 } else if (param->dtmf == '#')
1876 if (e_dtmf_last>='0' && e_dtmf_last<='9')
1878 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf sequence *%c# detected.\n", ea_endpoint->ep_serial, e_dtmf_last);
1879 if (e_dtmf_last == '0')
1884 /* processing keypad function */
1886 keypad_function(e_dtmf_last);
1892 /* set last time of dtmf */
1897 /* check for ## hookflash during dialing */
1899 if (e_action->index==ACTION_PASSWORD
1900 || e_action->index==ACTION_PASSWORD_WRITE)
1902 if (param->dtmf=='#') /* current digit is '#' */
1904 if (e_state==EPOINT_STATE_IN_DISCONNECT
1905 || (e_state!=EPOINT_STATE_CONNECT && e_dtmf_time+3>=now && e_dtmf_last=='#')) /* when disconnected, just #. when dialing, ##. */
1922 /* dialing using dtmf digit */
1923 if (e_state==EPOINT_STATE_IN_OVERLAP)// && e_state==e_connectedmode)
1925 if (e_dialinginfo.number[0]=='\0' && !e_action)
1927 set_tone(portlist, "dialing");
1929 /* concat dialing string */
1930 if (strlen(e_dialinginfo.number)+1 < sizeof(e_dialinginfo.number))
1932 e_dialinginfo.number[strlen(e_dialinginfo.number)+1] = '\0';
1933 e_dialinginfo.number[strlen(e_dialinginfo.number)] = param->dtmf;
1939 /* port MESSAGE_CRYPT */
1940 void EndpointAppPBX::port_crypt(struct port_list *portlist, int message_type, union parameter *param)
1942 /* send crypt response to cryptman */
1943 if (param->crypt.type == CR_MESSAGE_IND)
1944 cryptman_msg2man(param->crypt.data, param->crypt.len);
1946 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
1949 /* port MESSAGE_OVERLAP */
1950 void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, union parameter *param)
1952 struct message *message;
1954 /* signal to call tool */
1955 admin_call_response(e_adminid, ADMIN_CALL_SETUP_ACK, "", 0, 0, 0);
1957 printlog("%3d incoming SETUP ACKNOWLEDGE\n",
1958 ea_endpoint->ep_serial
1960 if (e_dialing_queue[0] && portlist)
1962 /* send what we have not dialed yet, because we had no setup complete */
1963 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing pending digits: '%s'\n", ea_endpoint->ep_serial, e_dialing_queue);
1964 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
1965 SCPY(message->param.information.number, e_dialing_queue);
1966 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
1967 message_put(message);
1968 logmessage(message);
1969 e_dialing_queue[0] = '\0';
1971 /* check if pattern is available */
1972 if (!ea_endpoint->ep_portlist->next && portlist->earlyb) /* one port_list relation and tones available */
1974 /* indicate patterns */
1975 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_PATTERN);
1976 message_put(message);
1978 /* connect audio, if not already */
1979 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
1980 message->param.channel = CHANNEL_STATE_CONNECT;
1981 message_put(message);
1984 /* indicate no patterns */
1985 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_NOPATTERN);
1986 message_put(message);
1988 /* disconnect audio, if not already */
1989 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
1990 message->param.channel = CHANNEL_STATE_HOLD;
1991 message_put(message);
1993 new_state(EPOINT_STATE_OUT_OVERLAP);
1994 /* if we are in a call */
1995 if (ea_endpoint->ep_call_id)
1997 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
1998 memcpy(&message->param, param, sizeof(union parameter));
1999 message_put(message);
2003 /* port MESSAGE_PROCEEDING */
2004 void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_type, union parameter *param)
2006 struct message *message;
2008 /* signal to call tool */
2009 admin_call_response(e_adminid, ADMIN_CALL_PROCEEDING, "", 0, 0, 0);
2011 printlog("%3d incoming PROCEEDING\n",
2012 ea_endpoint->ep_serial
2014 e_state = EPOINT_STATE_OUT_PROCEEDING;
2015 /* check if pattern is availatle */
2016 if (!ea_endpoint->ep_portlist->next && (portlist->earlyb || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
2018 /* indicate patterns */
2019 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_PATTERN);
2020 message_put(message);
2022 /* connect audio, if not already */
2023 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2024 message->param.channel = CHANNEL_STATE_CONNECT;
2025 message_put(message);
2028 /* indicate no patterns */
2029 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_NOPATTERN);
2030 message_put(message);
2032 /* disconnect audio, if not already */
2033 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2034 message->param.channel = CHANNEL_STATE_HOLD;
2035 message_put(message);
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_ALERTING */
2047 void EndpointAppPBX::port_alerting(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_ALERTING, "", 0, 0, 0);
2054 printlog("%3d incoming ALERTING\n",
2055 ea_endpoint->ep_serial
2057 new_state(EPOINT_STATE_OUT_ALERTING);
2058 /* check if pattern is available */
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_CONNECT */
2090 void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, union parameter *param)
2092 struct message *message;
2094 unsigned long port_id = portlist->port_id;
2095 struct port_list *tportlist;
2098 /* signal to call tool */
2099 admin_call_response(e_adminid, ADMIN_CALL_CONNECT, numberrize_callerinfo(param->connectinfo.id,param->connectinfo.ntype), 0, 0, 0);
2101 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_connectinfo));
2102 printlog("%3d incoming CONNECT id='%s'%s\n",
2103 ea_endpoint->ep_serial,
2104 (e_connectinfo.intern[0])?e_connectinfo.intern:e_connectinfo.id,
2105 (e_connectinfo.present==INFO_PRESENT_RESTRICTED)?" anonymous":""
2107 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (start)\n", ea_endpoint->ep_serial);
2108 while(ea_endpoint->ep_portlist->next) /* as long as we have at least two ports */
2110 tportlist = ea_endpoint->ep_portlist;
2111 if (tportlist->port_id == port_id) /* if the first portlist is the calling one, the second must be a different one */
2112 tportlist = tportlist->next;
2113 if (tportlist->port_id == port_id)
2115 PERROR("EPOINT(%d) software error: this should not happen since the portlist list must not have two links to the same port - exitting.\n");
2118 message = message_create(ea_endpoint->ep_serial, tportlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2119 message->param.disconnectinfo.cause = 26; /* non selected user clearing */
2120 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2121 message_put(message);
2122 logmessage(message);
2123 ea_endpoint->free_portlist(tportlist);
2125 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (end)\n", ea_endpoint->ep_serial);
2129 /* screen by interface */
2130 if (e_callerinfo.interface[0])
2132 /* screen incoming caller id */
2133 screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present);
2136 /* screen connected name */
2138 SCPY(e_connectinfo.name, e_ext.name);
2140 /* add internal id to colp */
2141 SCPY(e_connectinfo.intern, e_terminal);
2143 /* we store the connected port number */
2144 SCPY(e_terminal_interface, e_connectinfo.interfaces);
2146 /* for internal and am calls, we get the extension's id */
2147 if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE)
2149 SCPY(e_connectinfo.id, e_ext.callerid);
2150 SCPY(e_connectinfo.intern, e_terminal);
2151 e_connectinfo.itype = INFO_ITYPE_INTERN;
2152 e_connectinfo.ntype = e_ext.callerid_type;
2153 e_connectinfo.present = e_ext.callerid_present;
2155 if (portlist->port_type==PORT_TYPE_VBOX_OUT)
2157 e_connectinfo.itype = INFO_ITYPE_VBOX;
2158 e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2161 new_state(EPOINT_STATE_CONNECT);
2163 /* set volume of rx and tx */
2164 if (e_ext.txvol!=256 || e_ext.rxvol!=256)
2166 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2167 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2168 message->param.mISDNsignal.rxvol = e_ext.txvol;
2169 message->param.mISDNsignal.txvol = e_ext.rxvol;
2170 message_put(message);
2173 e_cfnr_call = e_cfnr_release = 0;
2175 e_dtmf = 1; /* allow dtmf */
2176 // if (call_countrelations(ea_endpoint->ep_call_id) == 2)
2179 /* other calls with no caller id (or not available for the extension) and force colp */
2180 if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE)
2182 e_connectinfo.present = INFO_PRESENT_NOTAVAIL;
2183 if (portlist->port_type==PORT_TYPE_DSS1_TE_OUT || portlist->port_type==PORT_TYPE_DSS1_NT_OUT) /* external extension answered */
2185 port = find_port_id(portlist->port_id);
2188 SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.number, &e_connectinfo.ntype));
2189 e_connectinfo.present = INFO_PRESENT_ALLOWED;
2193 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
2194 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
2195 message_put(message);
2197 if (ea_endpoint->ep_call_id)
2199 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2200 message->param.channel = CHANNEL_STATE_CONNECT;
2201 message_put(message);
2202 } else if (!e_adminid)
2205 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have a callback, so we create a call with cbcaller: \"%s\".\n", ea_endpoint->ep_serial, e_cbcaller);
2206 SCPY(e_terminal, e_cbcaller);
2207 new_state(EPOINT_STATE_IN_OVERLAP);
2208 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) callback from extension '%s'\n", ea_endpoint->ep_serial, e_terminal);
2210 /* get extension's info about terminal */
2211 if (!read_extension(&e_ext, e_terminal))
2213 /* extension doesn't exist */
2214 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_terminal);
2215 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
2216 new_state(EPOINT_STATE_OUT_DISCONNECT);
2217 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
2221 /* put prefix in front of e_cbdialing */
2222 SPRINT(buffer, "%s%s", e_ext.prefix, e_cbdialing);
2223 SCPY(e_dialinginfo.number, buffer);
2224 e_dialinginfo.itype = INFO_ITYPE_EXTERN;
2225 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
2227 /* use caller id (or if exist: id_next_call) for this call */
2228 e_callerinfo.screen = INFO_SCREEN_NETWORK;
2229 SCPY(e_callerinfo.intern, e_terminal);
2230 if (e_ext.id_next_call_present >= 0)
2232 SCPY(e_callerinfo.id, e_ext.id_next_call);
2233 e_callerinfo.present = e_ext.id_next_call_present;
2234 e_callerinfo.ntype = e_ext.id_next_call_type;
2235 e_ext.id_next_call_present = -1;
2236 /* extension is written */
2237 write_extension(&e_ext, e_terminal);
2240 SCPY(e_callerinfo.id, e_ext.callerid);
2241 e_callerinfo.present = e_ext.callerid_present;
2242 e_callerinfo.ntype = e_ext.callerid_type;
2245 e_connectedmode = 1; /* dtmf-hangup & disconnect prevention */
2248 /* check if caller id is NOT authenticated */
2249 if (!parse_callbackauth(e_terminal, &e_callbackinfo))
2251 /* make call state to enter password */
2252 new_state(EPOINT_STATE_IN_OVERLAP);
2253 e_action = &action_password_write;
2254 e_match_timeout = 0;
2255 e_match_to_action = NULL;
2256 e_dialinginfo.number[0] = '\0';
2257 e_extdialing = strchr(e_dialinginfo.number, '\0');
2258 e_password_timeout = now+20;
2262 /* incoming call (callback) */
2263 e_ruleset = ruleset_main;
2265 e_rule = e_ruleset->rule_first;
2267 e_extdialing = e_dialinginfo.number;
2268 if (e_dialinginfo.number[0])
2270 set_tone(portlist, "dialing");
2274 set_tone(portlist, "dialpbx");
2277 } else /* testcall */
2279 set_tone(portlist, "hold");
2282 /* start recording if enabled, not when answering machine answers */
2283 if (param->connectinfo.itype!=INFO_ITYPE_VBOX && e_terminal[0] && e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO))
2285 /* check if we are a terminal */
2286 if (e_terminal[0] == '\0')
2287 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
2290 port = find_port_id(portlist->port_id);
2292 port->open_record(e_ext.record, 0, 0, e_terminal, e_ext.anon_ignore, "", 0);
2297 /* port MESSAGE_DISCONNECT MESSAGE_RELEASE */
2298 void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
2300 struct message *message;
2302 unsigned long port_id = portlist->port_id;
2306 /* signal to call tool */
2307 admin_call_response(e_adminid, (message_type==MESSAGE_DISCONNECT)?ADMIN_CALL_DISCONNECT:ADMIN_CALL_RELEASE, "", param->disconnectinfo.cause, param->disconnectinfo.location, 0);
2309 printlog("%3d incoming %s cause='%d' (%s) location='%d' (%s)\n",
2310 ea_endpoint->ep_serial,
2311 (message_type==MESSAGE_DISCONNECT)?"DISCONNECT":"RELEASE",
2312 param->disconnectinfo.cause,
2313 (param->disconnectinfo.cause>0 && param->disconnectinfo.cause<128)?isdn_cause[param->disconnectinfo.cause].english:"-",
2314 param->disconnectinfo.location,
2315 (param->disconnectinfo.location>=0 && param->disconnectinfo.location<16)?isdn_location[param->disconnectinfo.location].english:"-"
2318 //#warning does this work? only disconnect when incoming port hat not already disconnected yet?
2319 if (e_state==EPOINT_STATE_IN_DISCONNECT && message_type!=MESSAGE_RELEASE)// || e_state==EPOINT_STATE_OUT_DISCONNECT || e_state==EPOINT_STATE_IDLE)
2321 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are already disconnected.\n", ea_endpoint->ep_serial);
2326 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);
2327 if (param->disconnectinfo.cause == CAUSE_REJECTED) /* call rejected */
2329 e_multipoint_cause = CAUSE_REJECTED;
2330 e_multipoint_location = param->disconnectinfo.location;
2332 if (param->disconnectinfo.cause==CAUSE_NORMAL && e_multipoint_cause!=CAUSE_REJECTED) /* reject via hangup */
2334 e_multipoint_cause = CAUSE_NORMAL;
2335 e_multipoint_location = param->disconnectinfo.location;
2337 if (param->disconnectinfo.cause==CAUSE_BUSY && e_multipoint_cause!=CAUSE_REJECTED && e_multipoint_cause!=CAUSE_NORMAL) /* busy */
2339 e_multipoint_cause = CAUSE_BUSY;
2340 e_multipoint_location = param->disconnectinfo.location;
2342 if (param->disconnectinfo.cause==CAUSE_OUTOFORDER && e_multipoint_cause!=CAUSE_BUSY && e_multipoint_cause!=CAUSE_REJECTED && e_multipoint_cause!=CAUSE_NORMAL) /* no L1 */
2344 e_multipoint_cause = CAUSE_OUTOFORDER;
2345 e_multipoint_location = param->disconnectinfo.location;
2347 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 */
2349 e_multipoint_cause = param->disconnectinfo.cause;
2350 e_multipoint_location = param->disconnectinfo.location;
2352 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new multipoint cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location);
2354 /* check if we have more than one portlist relation and we just ignore the disconnect */
2355 if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist->next)
2357 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the disconnect was from a multipoint call. we just release that relation.\n", ea_endpoint->ep_serial);
2358 portlist = ea_endpoint->ep_portlist;
2361 if (portlist->port_id == port_id)
2363 portlist = portlist->next;
2367 PERROR("EPOINT(%d) software error: no portlist related to the calling port.\n", ea_endpoint->ep_serial);
2370 if (message_type != MESSAGE_RELEASE)
2372 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2373 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2374 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2375 message_put(message);
2376 logmessage(message);
2378 ea_endpoint->free_portlist(portlist);
2379 return; /* one relation removed */
2381 if (e_multipoint_cause)
2383 cause = e_multipoint_cause;
2384 location = e_multipoint_location;
2387 cause = param->disconnectinfo.cause;
2388 location = param->disconnectinfo.location;
2391 e_cfnr_call = e_cfnr_release = 0;
2393 /* process hangup */
2394 process_hangup(e_call_cause, e_call_location);
2395 e_multipoint_cause = 0;
2396 e_multipoint_location = LOCATION_PRIVATE_LOCAL;
2398 /* tone to disconnected end */
2399 SPRINT(buffer, "cause_%02x", cause);
2400 if (ea_endpoint->ep_portlist)
2401 set_tone(ea_endpoint->ep_portlist, buffer);
2403 new_state(EPOINT_STATE_IN_DISCONNECT);
2404 if (ea_endpoint->ep_call_id)
2406 int haspatterns = 0;
2407 /* check if pattern is available */
2408 if (ea_endpoint->ep_portlist)
2409 if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->earlyb)
2410 #warning wie ist das bei einem asterisk, gibts auch tones?
2411 if (callpbx_countrelations(ea_endpoint->ep_call_id)==2 // we must count relations, in order not to disturb the conference ; NOTE:
2412 && message_type != MESSAGE_RELEASE) // if we release, we are done
2416 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has patterns.\n", ea_endpoint->ep_serial);
2417 /* indicate patterns */
2418 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_PATTERN);
2419 message_put(message);
2420 /* connect audio, if not already */
2421 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2422 message->param.channel = CHANNEL_STATE_CONNECT;
2423 message_put(message);
2424 /* send disconnect */
2425 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
2426 memcpy(&message->param, param, sizeof(union parameter));
2427 message_put(message);
2428 /* disable encryption if disconnected */
2429 //PERROR("REMOVE ME: state =%d, %d\n", e_crypt_state, e_crypt);
2431 cryptman_message(CI_DISCONNECT_IND, NULL, 0);
2435 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
2438 release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, callcause, portcause */
2439 return; /* must exit here */
2442 /* port MESSAGE_TIMEOUT */
2443 void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type, union parameter *param)
2447 printlog("%3d incoming TIMEOUT\n",
2448 ea_endpoint->ep_serial
2450 message_type = MESSAGE_DISCONNECT;
2451 switch (param->state)
2453 case PORT_STATE_OUT_SETUP:
2454 case PORT_STATE_OUT_OVERLAP:
2455 /* no user responding */
2456 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2457 return; /* must exit here */
2459 case PORT_STATE_IN_SETUP:
2460 case PORT_STATE_IN_OVERLAP:
2461 param->disconnectinfo.cause = CAUSE_INVALID; /* number incomplete */
2462 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2465 case PORT_STATE_OUT_PROCEEDING:
2466 param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
2467 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2468 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2469 return; /* must exit here */
2471 case PORT_STATE_IN_PROCEEDING:
2472 param->disconnectinfo.cause = CAUSE_NOUSER;
2473 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL; /* no user responding */
2476 case PORT_STATE_OUT_ALERTING:
2477 param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
2478 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2479 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2480 return; /* must exit here */
2482 case PORT_STATE_IN_ALERTING:
2483 param->disconnectinfo.cause = CAUSE_NOANSWER;
2484 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2487 case PORT_STATE_IN_DISCONNECT:
2488 case PORT_STATE_OUT_DISCONNECT:
2489 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
2490 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2491 return; /* must exit here */
2494 param->disconnectinfo.cause = 31; /* normal unspecified */
2495 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2497 /* release call, disconnect isdn */
2499 new_state(EPOINT_STATE_OUT_DISCONNECT);
2500 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2501 SCPY(e_tone, cause);
2504 set_tone(portlist, cause);
2505 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2506 portlist = portlist->next;
2508 release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
2511 /* port MESSAGE_NOTIFY */
2512 void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, union parameter *param)
2514 struct message *message;
2518 /* signal to call tool */
2519 admin_call_response(e_adminid, ADMIN_CALL_NOTIFY, numberrize_callerinfo(param->notifyinfo.id,param->notifyinfo.ntype), 0, 0, param->notifyinfo.notify);
2520 if (param->notifyinfo.notify)
2522 e_rx_state = track_notify(e_rx_state, param->notifyinfo.notify);
2525 /* if we get notification from stack, local shows if we disabled/enabled audio stream */
2526 if (param->notifyinfo.local) switch(param->notifyinfo.notify)
2528 case INFO_NOTIFY_REMOTE_HOLD:
2529 case INFO_NOTIFY_USER_SUSPENDED:
2530 /* tell call about it */
2531 if (ea_endpoint->ep_call_id)
2533 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2534 message->param.channel = CHANNEL_STATE_HOLD;
2535 message_put(message);
2539 case INFO_NOTIFY_REMOTE_RETRIEVAL:
2540 case INFO_NOTIFY_USER_RESUMED:
2541 /* set volume of rx and tx */
2542 if (param->setup.callerinfo.itype == INFO_ITYPE_INTERN)
2543 if (e_ext.txvol!=256 || e_ext.rxvol!=256)
2546 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2547 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2548 message->param.mISDNsignal.rxvol = e_ext.txvol;
2549 message->param.mISDNsignal.txvol = e_ext.rxvol;
2550 message_put(message);
2552 /* set current tone */
2554 set_tone(portlist, e_tone);
2555 /* tell call about it */
2556 if (ea_endpoint->ep_call_id)
2558 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2559 message->param.channel = CHANNEL_STATE_CONNECT;
2560 message_put(message);
2565 /* get name of notify */
2566 switch(param->notifyinfo.notify)
2572 logtext = "USER_SUSPENDED";
2575 logtext = "BEARER_SERVICE_CHANGED";
2578 logtext = "USER_RESUMED";
2581 logtext = "CONFERENCE_ESTABLISHED";
2584 logtext = "CONFERENCE_DISCONNECTED";
2587 logtext = "OTHER_PARTY_ADDED";
2590 logtext = "ISOLATED";
2593 logtext = "REATTACHED";
2596 logtext = "OTHER_PARTY_ISOLATED";
2599 logtext = "OTHER_PARTY_REATTACHED";
2602 logtext = "OTHER_PARTY_SPLIT";
2605 logtext = "OTHER_PARTY_DISCONNECTED";
2608 logtext = "CONFERENCE_FLOATING";
2611 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
2614 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
2617 logtext = "CALL_IS_A_WAITING_CALL";
2620 logtext = "DIVERSION_ACTIVATED";
2623 logtext = "RESERVED_CT_1";
2626 logtext = "RESERVED_CT_2";
2629 logtext = "REVERSE_CHARGING";
2632 logtext = "REMOTE_HOLD";
2635 logtext = "REMOTE_RETRIEVAL";
2638 logtext = "CALL_IS_DIVERTING";
2641 SPRINT(buffer, "indicator=%d", param->notifyinfo.notify - 0x80);
2645 printlog("%3d incoming NOTIFY notify='%s' id='%s'%s\n",
2646 ea_endpoint->ep_serial,
2648 param->notifyinfo.id,
2649 (param->notifyinfo.present==INFO_PRESENT_RESTRICTED)?" anonymous":""
2652 /* notify call if available */
2653 if (ea_endpoint->ep_call_id)
2655 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_NOTIFY);
2656 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
2657 message_put(message);
2662 /* port MESSAGE_FACILITY */
2663 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
2665 struct message *message;
2667 printlog("%3d incoming FACILITY len='%d'\n",
2668 ea_endpoint->ep_serial,
2669 param->facilityinfo.len
2672 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_FACILITY);
2673 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2674 message_put(message);
2677 /* port MESSAGE_SUSPEND */
2678 /* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
2679 void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
2681 printlog("%3d incoming SUSPEND\n",
2682 ea_endpoint->ep_serial
2684 /* epoint is now parked */
2685 ea_endpoint->ep_park = 1;
2686 memcpy(ea_endpoint->ep_park_callid, param->parkinfo.callid, sizeof(ea_endpoint->ep_park_callid));
2687 ea_endpoint->ep_park_len = (param->parkinfo.len>8)?8:param->parkinfo.len;
2689 /* remove port relation */
2690 ea_endpoint->free_portlist(portlist);
2693 /* port MESSAGE_RESUME */
2694 /* NOTE: before resume, the active-notification must be done in order to set call mixer */
2695 void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
2697 printlog("%3d incoming RESUME\n",
2698 ea_endpoint->ep_serial
2700 /* epoint is now resumed */
2701 ea_endpoint->ep_park = 0;
2706 /* port sends message to the endpoint
2708 void EndpointAppPBX::ea_message_port(unsigned long port_id, int message_type, union parameter *param)
2710 struct port_list *portlist;
2711 struct message *message;
2714 portlist = ea_endpoint->ep_portlist;
2717 if (port_id == portlist->port_id)
2719 portlist = portlist->next;
2723 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);
2727 // PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_terminal, e_callerinfo.id);
2728 switch(message_type)
2730 case MESSAGE_DATA: /* data from port */
2731 /* send back to source for recording */
2734 message = message_create(ea_endpoint->ep_serial, port_id, EPOINT_TO_PORT, message_type);
2735 memcpy(&message->param, param, sizeof(union parameter));
2736 message_put(message);
2739 /* check if there is a call */
2740 if (!ea_endpoint->ep_call_id)
2742 /* continue if only one portlist */
2743 if (ea_endpoint->ep_portlist->next != NULL)
2745 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
2746 memcpy(&message->param, param, sizeof(union parameter));
2747 message_put(message);
2750 case MESSAGE_TONE_EOF: /* tone is end of file */
2751 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
2754 if (e_action->index == ACTION_VBOX_PLAY)
2758 if (e_action->index == ACTION_EFI)
2765 case MESSAGE_TONE_COUNTER: /* counter info received */
2766 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);
2768 if (e_action->index == ACTION_VBOX_PLAY)
2770 e_vbox_counter = param->counter.current;
2771 if (param->counter.max >= 0)
2772 e_vbox_counter_max = param->counter.max;
2776 /* PORT sends SETUP message */
2778 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);
2779 if (e_state!=EPOINT_STATE_IDLE)
2781 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
2784 port_setup(portlist, message_type, param);
2787 /* PORT sends INFORMATION message */
2788 case MESSAGE_INFORMATION: /* additional digits received */
2789 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call dialing more=%s (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, param->information.number, e_terminal, e_callerinfo.id);
2790 port_information(portlist, message_type, param);
2793 /* PORT sends FACILITY message */
2794 case MESSAGE_FACILITY:
2795 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id);
2796 port_facility(portlist, message_type, param);
2799 /* PORT sends DTMF message */
2800 case MESSAGE_DTMF: /* dtmf digits received */
2801 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf digit=%c (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, param->dtmf, e_terminal, e_callerinfo.id);
2802 port_dtmf(portlist, message_type, param);
2805 /* PORT sends CRYPT message */
2806 case MESSAGE_CRYPT: /* crypt response received */
2807 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) crypt response=%d\n", ea_endpoint->ep_serial, param->crypt.type);
2808 port_crypt(portlist, message_type, param);
2811 /* PORT sends MORE message */
2812 case MESSAGE_OVERLAP:
2813 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) outgoing call is accepted [overlap dialing] (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id);
2814 if (e_state != EPOINT_STATE_OUT_SETUP)
2816 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);
2819 port_overlap(portlist, message_type, param);
2822 /* PORT sends PROCEEDING message */
2823 case MESSAGE_PROCEEDING: /* port is proceeding */
2824 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) outgoing call is proceeding (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id);
2825 if (e_state!=EPOINT_STATE_OUT_SETUP
2826 && e_state!=EPOINT_STATE_OUT_OVERLAP)
2828 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);
2831 port_proceeding(portlist, message_type, param);
2834 /* PORT sends ALERTING message */
2835 case MESSAGE_ALERTING:
2836 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) outgoing call is ringing (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id);
2837 if (e_state!=EPOINT_STATE_OUT_SETUP
2838 && e_state!=EPOINT_STATE_OUT_OVERLAP
2839 && e_state!=EPOINT_STATE_OUT_PROCEEDING)
2841 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);
2844 port_alerting(portlist, message_type, param);
2847 /* PORT sends CONNECT message */
2848 case MESSAGE_CONNECT:
2849 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) outgoing call connected to %s (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_connectinfo.id, e_terminal, e_callerinfo.id);
2850 if (e_state!=EPOINT_STATE_OUT_SETUP
2851 && e_state!=EPOINT_STATE_OUT_OVERLAP
2852 && e_state!=EPOINT_STATE_OUT_PROCEEDING
2853 && e_state!=EPOINT_STATE_OUT_ALERTING)
2855 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
2858 port_connect(portlist, message_type, param);
2861 /* PORT sends DISCONNECT message */
2862 case MESSAGE_DISCONNECT: /* port is disconnected */
2863 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_terminal, e_callerinfo.id);
2864 port_disconnect_release(portlist, message_type, param);
2867 /* PORT sends a RELEASE message */
2868 case MESSAGE_RELEASE: /* port releases */
2869 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_terminal, e_callerinfo.id);
2870 /* portlist is release at port_disconnect_release, thanx Paul */
2871 port_disconnect_release(portlist, message_type, param);
2874 /* PORT sends a TIMEOUT message */
2875 case MESSAGE_TIMEOUT:
2876 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received timeout (state=%d).\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id, param->state);
2877 port_timeout(portlist, message_type, param);
2878 break; /* release */
2880 /* PORT sends a NOTIFY message */
2881 case MESSAGE_NOTIFY:
2882 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received notify.\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id);
2883 port_notify(portlist, message_type, param);
2886 /* PORT sends a SUSPEND message */
2887 case MESSAGE_SUSPEND:
2888 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received suspend.\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id);
2889 port_suspend(portlist, message_type, param);
2890 break; /* suspend */
2892 /* PORT sends a RESUME message */
2893 case MESSAGE_RESUME:
2894 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received resume.\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id);
2895 port_resume(portlist, message_type, param);
2898 case MESSAGE_VBOX_RECORD:
2899 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received recording message from vbox.\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id);
2900 /* check if we are a terminal */
2901 if (e_terminal[0] == '\0')
2902 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
2905 port = find_port_id(portlist->port_id);
2907 port->open_record(e_ext.vbox_codec, 2, 0, e_terminal, e_ext.anon_ignore, e_ext.vbox_email, e_ext.vbox_email_file);
2909 /* the recording is done to the vbox directory rather than to the recording directory (using vbox_codec) */
2913 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received a wrong message: %d\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id, message);
2916 /* Note: this endpoint may be destroyed, so we MUST return */
2920 /* messages from port
2922 /* call MESSAGE_CRYPT */
2923 void EndpointAppPBX::call_crypt(struct port_list *portlist, int message_type, union parameter *param)
2925 switch(param->crypt.type)
2927 /* message from remote port to "crypt manager" */
2928 case CU_ACTK_REQ: /* activate key-exchange */
2929 case CU_ACTS_REQ: /* activate shared key */
2930 case CU_DACT_REQ: /* deactivate */
2931 case CU_INFO_REQ: /* request last info message */
2932 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2935 /* message from "crypt manager" to user */
2936 case CU_ACTK_CONF: /* key-echange done */
2937 case CU_ACTS_CONF: /* shared key done */
2938 case CU_DACT_CONF: /* deactivated */
2939 case CU_DACT_IND: /* deactivated */
2940 case CU_ERROR_IND: /* receive error message */
2941 case CU_INFO_IND: /* receive info message */
2942 case CU_INFO_CONF: /* receive info message */
2943 encrypt_result(param->crypt.type, (char *)param->crypt.data);
2947 PERROR("EPOINT(%d) epoint with terminal '%s' (caller id '%s') unknown crypt message: '%d'\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id, param->crypt.type);
2951 /* call MESSAGE_INFORMATION */
2952 void EndpointAppPBX::call_information(struct port_list *portlist, int message_type, union parameter *param)
2954 struct message *message;
2960 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2961 memcpy(&message->param.information, ¶m->information, sizeof(struct dialing_info));
2962 message_put(message);
2963 logmessage(message);
2964 portlist = portlist->next;
2968 /* call MESSAGE_FACILITY */
2969 void EndpointAppPBX::call_facility(struct port_list *portlist, int message_type, union parameter *param)
2971 struct message *message;
2973 if (!e_ext.facility)
2980 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_FACILITY);
2981 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2982 message_put(message);
2983 logmessage(message);
2984 portlist = portlist->next;
2988 /* call MESSAGE_MORE */
2989 void EndpointAppPBX::call_overlap(struct port_list *portlist, int message_type, union parameter *param)
2991 struct message *message;
2993 new_state(EPOINT_STATE_IN_OVERLAP);
2996 if (e_call_pattern && e_ext.own_setup)
2998 /* disconnect audio */
2999 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3000 message->param.channel = CHANNEL_STATE_HOLD;
3001 message_put(message);
3003 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
3005 set_tone(portlist, "dialtone");
3009 set_tone(portlist, "dialpbx");
3011 set_tone(portlist, "dialtone");
3014 /* call MESSAGE_PROCEEDING */
3015 void EndpointAppPBX::call_proceeding(struct port_list *portlist, int message_type, union parameter *param)
3017 struct message *message;
3019 new_state(EPOINT_STATE_IN_PROCEEDING);
3021 /* own proceeding tone */
3024 /* connect / disconnect audio */
3025 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3026 if (e_ext.own_proceeding)
3027 message->param.channel = CHANNEL_STATE_HOLD;
3029 message->param.channel = CHANNEL_STATE_CONNECT;
3030 message_put(message);
3032 // UCPY(e_call_tone, "proceeding");
3035 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3036 message_put(message);
3037 logmessage(message);
3039 set_tone(portlist, "proceeding");
3042 /* call MESSAGE_ALERTING */
3043 void EndpointAppPBX::call_alerting(struct port_list *portlist, int message_type, union parameter *param)
3045 struct message *message;
3047 new_state(EPOINT_STATE_IN_ALERTING);
3049 /* own alerting tone */
3052 /* connect / disconnect audio */
3053 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3054 if (e_ext.own_alerting)
3055 message->param.channel = CHANNEL_STATE_HOLD;
3057 message->param.channel = CHANNEL_STATE_CONNECT;
3058 message_put(message);
3062 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
3063 message_put(message);
3064 logmessage(message);
3066 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
3068 set_tone(portlist, "ringing");
3072 set_tone(portlist, "ringpbx");
3074 set_tone(portlist, "ringing");
3077 /* call MESSAGE_CONNECT */
3078 void EndpointAppPBX::call_connect(struct port_list *portlist, int message_type, union parameter *param)
3080 struct message *message;
3082 new_state(EPOINT_STATE_CONNECT);
3083 // UCPY(e_call_tone, "");
3085 e_dtmf = 1; /* allow dtmf */
3087 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_callerinfo));
3090 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3091 memcpy(&message->param, param, sizeof(union parameter));
3092 /* screen by interface */
3093 if (e_connectinfo.interface[0])
3095 /* screen incoming caller id */
3096 screen(1, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present);
3098 memcpy(&message->param.connnectinfo, e_connectinfo);
3100 /* screen clip if prefix is required */
3101 if (e_terminal[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0])
3103 SCPY(message->param.connectinfo.id, e_ext.clip_prefix);
3104 SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype));
3105 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
3108 /* use internal caller id */
3109 if (e_terminal[0] && e_connectinfo.intern[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
3111 SCPY(message->param.connectinfo.id, e_connectinfo.intern);
3112 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
3115 /* handle restricted caller ids */
3116 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);
3117 /* display callerid if desired for extension */
3118 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));
3120 /* use conp, if enabld */
3122 message->param.connectinfo.name[0] = '\0';
3125 message_put(message);
3126 logmessage(message);
3128 set_tone(portlist, NULL);
3130 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3131 message->param.channel = CHANNEL_STATE_CONNECT;
3132 message_put(message);
3136 /* call MESSAGE_DISCONNECT MESSAGE_RELEASE */
3137 void EndpointAppPBX::call_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
3140 struct message *message;
3143 /* be sure that we are active */
3145 e_tx_state = NOTIFY_STATE_ACTIVE;
3147 /* we are powerdialing, if e_powerdialing is set and limit is not exceeded if given */
3148 if (e_powerdialing && ((e_powercount+1)<e_powerlimit || e_powerlimit<1))
3150 release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
3152 /* set time for power dialing */
3153 e_powerdialing = now_d + e_powerdelay; /* set redial in the future */
3156 /* set redial tone */
3157 if (ea_endpoint->ep_portlist)
3161 set_tone(ea_endpoint->ep_portlist, "redial");
3162 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') redialing in %d seconds\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id, (int)e_powerdelay);
3163 /* send proceeding when powerdialing and still setup (avoid dialing timeout) */
3164 if (e_state==EPOINT_STATE_IN_OVERLAP)
3166 new_state(EPOINT_STATE_IN_PROCEEDING);
3169 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3170 message_put(message);
3171 logmessage(message);
3173 /* caused the error, that the first knock sound was not there */
3174 /* set_tone(portlist, "proceeding"); */
3176 /* send display of powerdialing */
3177 if (e_ext.display_dialing)
3181 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3183 SPRINT(message->param.notifyinfo.display, "Retry %d of %d", e_powercount, e_powerlimit);
3185 SPRINT(message->param.notifyinfo.display, "Retry %d", e_powercount);
3186 message_put(message);
3187 logmessage(message);
3188 portlist = portlist->next;
3197 if ((e_state!=EPOINT_STATE_CONNECT
3198 && e_state!=EPOINT_STATE_OUT_DISCONNECT
3199 && e_state!=EPOINT_STATE_IN_OVERLAP
3200 && e_state!=EPOINT_STATE_IN_PROCEEDING
3201 && e_state!=EPOINT_STATE_IN_ALERTING)
3202 || !ea_endpoint->ep_portlist) /* or no port */
3204 process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
3205 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause); /* RELEASE_TYPE, call, port */
3206 return; /* must exit here */
3211 e_call_cause = param->disconnectinfo.cause;
3212 e_call_location = param->disconnectinfo.location;
3215 /* on release we need the audio again! */
3216 if (message_type == MESSAGE_RELEASE)
3219 ea_endpoint->ep_call_id = 0;
3221 /* disconnect and select tone */
3222 new_state(EPOINT_STATE_OUT_DISCONNECT);
3223 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
3224 /* if own_cause, we must release the call */
3225 if (e_ext.own_cause /* own cause */
3226 || !e_call_pattern) /* no patterns */
3228 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);
3229 if (message_type != MESSAGE_RELEASE)
3230 release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
3232 } else /* else we enable audio */
3234 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3235 message->param.channel = CHANNEL_STATE_CONNECT;
3236 message_put(message);
3238 /* send disconnect message */
3239 SCPY(e_tone, cause);
3242 set_tone(portlist, cause);
3243 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
3244 portlist = portlist->next;
3248 /* call MESSAGE_SETUP */
3249 void EndpointAppPBX::call_setup(struct port_list *portlist, int message_type, union parameter *param)
3251 struct message *message;
3253 /* if we already in setup state, we just update the dialing with new digits */
3254 if (e_state == EPOINT_STATE_OUT_SETUP
3255 || e_state == EPOINT_STATE_OUT_OVERLAP)
3257 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we are in setup state, so we do overlap dialing.\n", ea_endpoint->ep_serial);
3258 /* if digits changed, what we have already dialed */
3259 if (!!strncmp(e_dialinginfo.number,param->setup.dialinginfo.number,strlen(e_dialinginfo.number)))
3261 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);
3262 /* release all ports */
3263 while((portlist = ea_endpoint->ep_portlist))
3265 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
3266 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
3267 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3268 message_put(message);
3269 logmessage(message);
3270 ea_endpoint->free_portlist(portlist);
3273 /* disconnect audio */
3274 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3275 message->param.channel = CHANNEL_STATE_HOLD;
3276 message_put(message);
3278 /* get dialing info */
3279 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3280 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3281 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3282 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3283 new_state(EPOINT_STATE_OUT_OVERLAP);
3286 e_redial = now_d + 1; /* set redial one second in the future */
3289 /* if we have a pending redial, so we just adjust the dialing number */
3292 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);
3293 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3296 if (!ea_endpoint->ep_portlist)
3298 PERROR("ERROR: overlap dialing to a NULL port relation\n");
3300 if (ea_endpoint->ep_portlist->next)
3302 PERROR("ERROR: overlap dialing to a port_list port relation\n");
3304 if (e_state == EPOINT_STATE_OUT_SETUP)
3307 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);
3308 SCAT(e_dialing_queue, param->setup.dialinginfo.number + strlen(e_dialinginfo.number));
3312 /* get what we have not dialed yet */
3313 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));
3314 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
3315 SCPY(message->param.information.number, param->setup.dialinginfo.number + strlen(e_dialinginfo.number));
3316 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
3317 message_put(message);
3318 logmessage(message);
3320 /* always store what we have dialed or queued */
3321 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3325 if (e_state != EPOINT_STATE_IDLE)
3327 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
3330 /* if an internal extension is dialed, copy that number */
3331 if (param->setup.dialinginfo.itype==INFO_ITYPE_INTERN || param->setup.dialinginfo.itype==INFO_ITYPE_VBOX)
3332 SCPY(e_terminal, param->setup.dialinginfo.number);
3333 /* if an internal extension is dialed, get extension's info about caller */
3336 if (!read_extension(&e_ext, e_terminal))
3338 e_terminal[0] = '\0';
3339 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the called terminal='%s' is not found in directory tree!\n", ea_endpoint->ep_serial, e_terminal);
3343 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3344 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3345 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3346 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3348 /* screen by interface */
3349 if (e_callerinfo.interface[0])
3351 /* screen incoming caller id */
3352 screen(1, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present);
3355 /* process (voice over) data calls */
3356 if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO)
3358 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) handling data call as audio call: '%s'\n", ea_endpoint->ep_serial, e_terminal);
3359 memset(&e_capainfo, 0, sizeof(e_capainfo));
3360 e_capainfo.bearer_capa = INFO_BC_AUDIO;
3361 e_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
3362 e_capainfo.bearer_info1 = (options.law=='u')?INFO_INFO1_ULAW:INFO_INFO1_ALAW;
3365 new_state(EPOINT_STATE_OUT_SETUP);
3366 /* call special setup routine */
3370 /* call MESSAGE_mISDNSIGNAL */
3371 void EndpointAppPBX::call_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param)
3373 struct message *message;
3377 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
3378 memcpy(&message->param, param, sizeof(union parameter));
3379 message_put(message);
3380 portlist = portlist->next;
3384 /* call MESSAGE_NOTIFY */
3385 void EndpointAppPBX::call_notify(struct port_list *portlist, int message_type, union parameter *param)
3387 struct message *message;
3390 if (param->notifyinfo.notify)
3392 new_state = track_notify(e_tx_state, param->notifyinfo.notify);
3393 // /* if notification was generated locally, we turn hold music on/off */
3394 // if (param->notifyinfo.local)
3395 // 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)
3400 if (new_state!=NOTIFY_STATE_HOLD && new_state!=NOTIFY_STATE_SUSPEND)
3404 set_tone(portlist, "");
3405 portlist = portlist->next;
3407 portlist = ea_endpoint->ep_portlist;
3412 if (new_state==NOTIFY_STATE_HOLD || new_state==NOTIFY_STATE_SUSPEND)
3416 set_tone(portlist, "hold");
3417 portlist = portlist->next;
3419 portlist = ea_endpoint->ep_portlist;
3424 /* save new state */
3425 e_tx_state = new_state;
3428 /* notify port(s) about it */
3431 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3432 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
3433 /* handle restricted caller ids */
3434 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);
3435 /* display callerid if desired for extension */
3436 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));
3437 message_put(message);
3438 logmessage(message);
3439 portlist = portlist->next;
3443 /* call sends messages to the endpoint
3445 void EndpointAppPBX::ea_message_call(unsigned long call_id, int message_type, union parameter *param)
3447 struct port_list *portlist;
3448 struct message *message;
3452 PERROR("EPOINT(%d) error: call == NULL.\n", ea_endpoint->ep_serial);
3456 portlist = ea_endpoint->ep_portlist;
3458 /* send MESSAGE_DATA to port */
3459 if (call_id == ea_endpoint->ep_call_id)
3461 if (message_type == MESSAGE_DATA)
3463 /* skip if no port relation */
3466 /* skip if more than one port relation */
3469 /* send audio data to port */
3470 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DATA);
3471 memcpy(&message->param, param, sizeof(union parameter));
3472 message_put(message);
3477 // 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_terminal, e_callerinfo.id, e_state);
3478 switch(message_type)
3480 /* CALL SENDS CRYPT message */
3482 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received crypt message: '%d'\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id, param->crypt.type);
3483 call_crypt(portlist, message_type, param);
3486 /* CALL sends INFORMATION message */
3487 case MESSAGE_INFORMATION:
3488 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received more digits: '%s'\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id, param->information.number);
3489 call_information(portlist, message_type, param);
3492 /* CALL sends FACILITY message */
3493 case MESSAGE_FACILITY:
3494 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received facility\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id);
3495 call_facility(portlist, message_type, param);
3498 /* CALL sends OVERLAP message */
3499 case MESSAGE_OVERLAP:
3500 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received 'more info available'\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id);
3501 if (e_state!=EPOINT_STATE_IN_SETUP
3502 && e_state!=EPOINT_STATE_IN_OVERLAP)
3504 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3507 call_overlap(portlist, message_type, param);
3510 /* CALL sends PROCEEDING message */
3511 case MESSAGE_PROCEEDING:
3512 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s (caller id '%s') received proceeding\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id);
3513 if(e_state!=EPOINT_STATE_IN_OVERLAP)
3515 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3518 call_proceeding(portlist, message_type, param);
3521 /* CALL sends ALERTING message */
3522 case MESSAGE_ALERTING:
3523 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received alerting\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id);
3524 if (e_state!=EPOINT_STATE_IN_OVERLAP
3525 && e_state!=EPOINT_STATE_IN_PROCEEDING)
3527 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state.\n", ea_endpoint->ep_serial);
3530 call_alerting(portlist, message_type, param);
3533 /* CALL sends CONNECT message */
3534 case MESSAGE_CONNECT:
3535 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received connect\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id);
3536 if (e_state!=EPOINT_STATE_IN_OVERLAP
3537 && e_state!=EPOINT_STATE_IN_PROCEEDING
3538 && e_state!=EPOINT_STATE_IN_ALERTING)
3540 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
3543 call_connect(portlist, message_type, param);
3546 /* CALL sends DISCONNECT/RELEASE message */
3547 case MESSAGE_DISCONNECT: /* call disconnect */
3548 case MESSAGE_RELEASE: /* call releases */
3549 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_terminal, e_callerinfo.id, (message_type==MESSAGE_DISCONNECT)?"disconnect":"release", param->disconnectinfo.cause, param->disconnectinfo.location);
3550 call_disconnect_release(portlist, message_type, param);
3553 /* CALL sends SETUP message */
3555 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);
3556 call_setup(portlist, message_type, param);
3560 /* CALL sends special mISDNSIGNAL message */
3561 case MESSAGE_mISDNSIGNAL: /* isdn message to port */
3562 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received mISDNsignal message.\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id);
3563 call_mISDNsignal(portlist, message_type, param);
3566 /* CALL has pattern available */
3567 case MESSAGE_PATTERN: /* indicating pattern available */
3568 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received pattern availability.\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id);
3569 if (!e_call_pattern)
3571 PDEBUG(DEBUG_EPOINT, "-> pattern becomes available\n");
3576 set_tone(portlist, NULL);
3577 portlist = portlist->next;
3579 /* connect our audio tx and rx (blueboxing should be possibe before connect :)*/
3580 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3581 message->param.channel = CHANNEL_STATE_CONNECT;
3582 message_put(message);
3583 // /* tell remote epoint to connect audio also, because we like to hear the patterns */
3584 // message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_REMOTE_AUDIO);
3585 // message->param.channel = CHANNEL_STATE_CONNECT;
3586 // message_put(message);
3587 // patterns are available, remote already connected audio
3591 /* CALL has no pattern available */
3592 case MESSAGE_NOPATTERN: /* indicating no pattern available */
3593 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received pattern NOT available.\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id);
3596 PDEBUG(DEBUG_EPOINT, "-> pattern becomes unavailable\n");
3598 /* disconnect our audio tx and rx */
3599 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3600 message->param.channel = CHANNEL_STATE_HOLD;
3601 message_put(message);
3606 /* CALL (dunno at the moment) */
3607 case MESSAGE_REMOTE_AUDIO:
3608 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received audio remote request.\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id);
3609 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3610 message->param.channel = param->channel;
3611 message_put(message);
3615 /* CALL sends a notify message */
3616 case MESSAGE_NOTIFY:
3617 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received notify.\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id);
3618 call_notify(portlist, message_type, param);
3622 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received a wrong message: #%d\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id, message);
3627 /* pick_call will connect the first incoming call found. the endpoint
3628 * will receivce a MESSAGE_CONNECT.
3630 int match_list(char *list, char *item)
3632 char *end, *next = NULL;
3634 /* no list make matching */
3640 /* eliminate white spaces */
3641 while (*list <= ' ')
3648 /* if end of list is reached, we return */
3649 if (list[0] == '\0')
3651 /* if we have more than one entry (left) */
3652 if ((end = strchr(list, ',')))
3655 next = end = strchr(list, '\0');
3656 while (*(end-1) <= ' ')
3658 /* if string part matches item */
3659 if (!strncmp(list, item, end-list))
3665 void EndpointAppPBX::pick_call(char *extensions)
3667 struct message *message;
3668 struct port_list *portlist;
3670 class EndpointAppPBX *eapp, *found;
3672 class CallPBX *callpbx;
3673 struct call_relation *relation;
3676 /* find an endpoint that is ringing internally or vbox with higher priority */
3679 eapp = apppbx_first;
3682 if (eapp!=this && ea_endpoint->ep_portlist)
3684 portlist = eapp->ea_endpoint->ep_portlist;
3687 if ((port = find_port_id(portlist->port_id)))
3689 if (port->p_type == PORT_TYPE_VBOX_OUT)
3691 if (match_list(extensions, eapp->e_terminal))
3698 if ((port->p_type==PORT_TYPE_DSS1_NT_OUT || port->p_type==PORT_TYPE_DSS1_TE_OUT)
3699 && port->p_state==PORT_STATE_OUT_ALERTING)
3700 if (match_list(extensions, eapp->e_terminal))
3705 portlist = portlist->next;
3713 /* if no endpoint found */
3716 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);
3718 set_tone(ea_endpoint->ep_portlist, "cause_10");
3719 message_disconnect_port(ea_endpoint->ep_portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
3720 new_state(EPOINT_STATE_OUT_DISCONNECT);
3725 if (ea_endpoint->ep_call_id)
3727 PERROR("EPOINT(%d) we already have a call. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3730 if (!eapp->ea_endpoint->ep_call_id)
3732 PERROR("EPOINT(%d) ringing endpoint has no call.\n", ea_endpoint->ep_serial);
3735 call = find_call_id(eapp->ea_endpoint->ep_call_id);
3738 PERROR("EPOINT(%d) ringing endpoint's call not found.\n", ea_endpoint->ep_serial);
3741 if (callpbx->c_type != CALL_TYPE_PBX)
3743 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ringing endpoint's call is not a PBX call, so we must reject.\n", ea_endpoint->ep_serial);
3746 callpbx = (class CallPBX *)call;
3747 relation = callpbx->c_relation;
3750 PERROR("EPOINT(%d) ringing endpoint's call has no relation. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3753 while (relation->epoint_id != eapp->ea_endpoint->ep_serial)
3755 relation = relation->next;
3758 PERROR("EPOINT(%d) ringing endpoint's call has no relation to that call. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3763 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found ringing endpoint: %d.\n", ea_endpoint->ep_serial, eapp->ea_endpoint->ep_serial);
3765 if (options.deb & DEBUG_EPOINT)
3767 class Call *debug_c = call_first;
3768 class Endpoint *debug_e = epoint_first;
3769 class Port *debug_p = port_first;
3771 callpbx_debug(callpbx, "EndpointAppPBX::pick_call(before)");
3773 PDEBUG(DEBUG_EPOINT, "showing all calls:\n");
3776 PDEBUG(DEBUG_EPOINT, "call=%ld\n", debug_c->c_serial);
3777 debug_c = debug_c->next;
3779 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3782 PDEBUG(DEBUG_EPOINT, "ep=%ld, call=%ld\n", debug_e->ep_serial, debug_e->ep_call_id);
3783 debug_e = debug_e->next;
3785 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3788 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld (active)\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3789 debug_p = debug_p->next;
3794 ea_endpoint->ep_call_id = eapp->ea_endpoint->ep_call_id; /* we get the call */
3795 relation->epoint_id = ea_endpoint->ep_serial; /* the call gets us */
3796 eapp->ea_endpoint->ep_call_id = 0; /* the ringing endpoint will get disconnected */
3798 /* connnecting our endpoint */
3799 new_state(EPOINT_STATE_CONNECT);
3801 set_tone(ea_endpoint->ep_portlist, NULL);
3803 /* now we send a release to the ringing endpoint */
3804 message = message_create(ea_endpoint->ep_call_id, eapp->ea_endpoint->ep_serial, CALL_TO_EPOINT, MESSAGE_RELEASE);
3805 message->param.disconnectinfo.cause = 26; /* non selected user clearing */
3806 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3807 message_put(message);
3809 /* we send a connect to the call with our caller id */
3810 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CONNECT);
3811 SCPY(message->param.connectinfo.id, e_callerinfo.id);
3812 message->param.connectinfo.present = e_callerinfo.present;
3813 message->param.connectinfo.screen = e_callerinfo.screen;
3814 message->param.connectinfo.itype = e_callerinfo.itype;
3815 message->param.connectinfo.ntype = e_callerinfo.ntype;
3816 message_put(message);
3818 /* we send a connect to our port with the remote callerid */
3819 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3820 SCPY(message->param.connectinfo.id, eapp->e_callerinfo.id);
3821 message->param.connectinfo.present = eapp->e_callerinfo.present;
3822 message->param.connectinfo.screen = eapp->e_callerinfo.screen;
3823 message->param.connectinfo.itype = eapp->e_callerinfo.itype;
3824 message->param.connectinfo.ntype = eapp->e_callerinfo.ntype;
3825 /* handle restricted caller ids */
3826 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);
3827 /* display callerid if desired for extension */
3828 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));
3829 message_put(message);
3831 /* we send a connect to the audio path (not for vbox) */
3832 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3833 message->param.channel = CHANNEL_STATE_CONNECT;
3834 message_put(message);
3836 /* beeing paranoid, we make call update */
3837 callpbx->c_mixer = 1;
3839 if (options.deb & DEBUG_EPOINT)
3841 class Call *debug_c = call_first;
3842 class Endpoint *debug_e = epoint_first;
3843 class Port *debug_p = port_first;
3845 callpbx_debug(callpbx, "EndpointAppPBX::pick_call(after)");
3847 PDEBUG(DEBUG_EPOINT, "showing all calls:\n");
3850 PDEBUG(DEBUG_EPOINT, "call=%ld\n", debug_c->c_serial);
3851 debug_c = debug_c->next;
3853 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3856 PDEBUG(DEBUG_EPOINT, "ep=%ld, call=%ld\n", debug_e->ep_serial, debug_e->ep_call_id);
3857 debug_e = debug_e->next;
3859 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3862 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3863 debug_p = debug_p->next;
3869 /* join calls (look for a call that is on hold (same isdn interface/terminal))
3871 void EndpointAppPBX::join_call(void)
3873 struct message *message;
3874 struct call_relation *our_relation, *other_relation;
3875 struct call_relation **our_relation_pointer, **other_relation_pointer;
3876 class Call *our_call, *other_call;
3877 class CallPBX *our_callpbx, *other_callpbx;
3878 class EndpointAppPBX *other_eapp; class Endpoint *temp_epoint;
3879 class Port *our_port, *other_port;
3880 class Pdss1 *our_pdss1, *other_pdss1;
3882 /* are we a candidate to join a call */
3883 our_call = find_call_id(ea_endpoint->ep_call_id);
3886 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our call doesn't exist anymore.\n", ea_endpoint->ep_serial);
3889 if (our_call->c_type != CALL_TYPE_PBX)
3891 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: call is not a pbx call.\n", ea_endpoint->ep_serial);
3894 our_callpbx = (class CallPBX *)our_call;
3895 if (!ea_endpoint->ep_portlist)
3897 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
3902 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
3905 our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
3908 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
3911 if ((our_port->p_type&PORT_CLASS_mISDN_MASK) != PORT_CLASS_mISDN_DSS1)
3913 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not isdn.\n", ea_endpoint->ep_serial);
3916 our_pdss1 = (class Pdss1 *)our_port;
3918 /* find an endpoint that is on hold and has the same mISDNport that we are on */
3919 other_eapp = apppbx_first;
3922 if (other_eapp == this)
3924 other_eapp = other_eapp->next;
3927 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_terminal, (other_eapp->ea_endpoint->ep_portlist)?"YES":"NO", other_eapp->ea_endpoint->ep_call_id);
3928 if (other_eapp->e_terminal[0] /* has terminal */
3929 && other_eapp->ea_endpoint->ep_portlist /* has port */
3930 && other_eapp->ea_endpoint->ep_call_id) /* has call */
3932 other_port = find_port_id(other_eapp->ea_endpoint->ep_portlist->port_id);
3933 if (other_port) /* port still exists */
3935 if (other_port->p_type==PORT_TYPE_DSS1_NT_OUT
3936 || other_port->p_type==PORT_TYPE_DSS1_NT_IN) /* port is isdn nt-mode */
3938 other_pdss1 = (class Pdss1 *)other_port;
3939 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);
3940 if (other_pdss1->p_m_hold /* port is on hold */
3941 && other_pdss1->p_m_mISDNport == our_pdss1->p_m_mISDNport /* same isdn interface */
3942 && other_pdss1->p_m_d_ces == our_pdss1->p_m_d_ces) /* same tei+sapi */
3946 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of other type!\n", ea_endpoint->ep_serial);
3950 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port doesn't exist enymore.\n", ea_endpoint->ep_serial);
3953 other_eapp = other_eapp->next;
3957 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn interface with port on hold.\n", ea_endpoint->ep_serial);
3960 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port on hold found.\n", ea_endpoint->ep_serial);
3962 /* if we have the same call */
3963 if (other_eapp->ea_endpoint->ep_call_id == ea_endpoint->ep_call_id)
3965 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we an the other have the same call.\n", ea_endpoint->ep_serial);
3968 other_call = find_call_id(other_eapp->ea_endpoint->ep_call_id);
3971 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other call doesn't exist anymore.\n", ea_endpoint->ep_serial);
3974 if (other_call->c_type != CALL_TYPE_PBX)
3976 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other call is not a pbx call.\n", ea_endpoint->ep_serial);
3979 other_callpbx = (class CallPBX *)other_call;
3980 if (our_callpbx->c_partyline && other_callpbx->c_partyline)
3982 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both calls are partylines.\n", ea_endpoint->ep_serial);
3986 /* remove relation to endpoint for call on hold */
3987 other_relation = other_callpbx->c_relation;
3988 other_relation_pointer = &other_callpbx->c_relation;
3989 while(other_relation)
3991 if (other_relation->epoint_id == other_eapp->ea_endpoint->ep_serial)
3993 /* detach other endpoint on hold */
3994 *other_relation_pointer = other_relation->next;
3995 memset(other_relation, 0, sizeof(struct call_relation));
3996 free(other_relation);
3998 other_relation = *other_relation_pointer;
3999 other_eapp->ea_endpoint->ep_call_id = NULL;
4003 /* change call/hold pointer of endpoint to the new call */
4004 temp_epoint = find_epoint_id(other_relation->epoint_id);
4007 if (temp_epoint->ep_call_id == other_call->c_serial)
4008 temp_epoint->ep_call_id = our_call->c_serial;
4011 other_relation_pointer = &other_relation->next;
4012 other_relation = other_relation->next;
4014 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint on hold removed, other enpoints on call relinked (to our call).\n", ea_endpoint->ep_serial);
4016 /* join call relations */
4017 our_relation = our_callpbx->c_relation;
4018 our_relation_pointer = &our_callpbx->c_relation;
4021 our_relation_pointer = &our_relation->next;
4022 our_relation = our_relation->next;
4024 *our_relation_pointer = other_callpbx->c_relation;
4025 other_callpbx->c_relation = NULL;
4026 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) relations joined.\n", ea_endpoint->ep_serial);
4028 /* release endpoint on hold */
4029 message = message_create(other_callpbx->c_serial, other_eapp->ea_endpoint->ep_serial, CALL_TO_EPOINT, MESSAGE_RELEASE);
4030 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */
4031 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
4032 message_put(message);
4034 /* if we are not a partyline, we get partyline state from other call */
4035 our_callpbx->c_partyline += other_callpbx->c_partyline;
4037 /* remove empty call */
4039 PDEBUG(DEBUG_EPOINT, "EPOINT(%d)d-call completely removed!\n");
4041 /* mixer must update */
4042 our_callpbx->c_mixer = 1; /* update mixer flag */
4044 /* we send a retrieve to that endpoint */
4045 // mixer will update the hold-state of the call and send it to the endpoints is changes
4049 /* check if we have an external call
4050 * this is used to check for encryption ability
4052 int EndpointAppPBX::check_external(char **errstr, class Port **port)
4054 struct call_relation *relation;
4056 class CallPBX *callpbx;
4057 class Endpoint *epoint;
4059 /* some paranoia check */
4060 if (!ea_endpoint->ep_portlist)
4062 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we have no port.\n", ea_endpoint->ep_serial);
4063 *errstr = "No Call";
4068 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we are not internal extension.\n", ea_endpoint->ep_serial);
4069 *errstr = "No Call";
4073 /* check if we have a call with 2 parties */
4074 call = find_call_id(ea_endpoint->ep_call_id);
4077 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have currently no call.\n", ea_endpoint->ep_serial);
4078 *errstr = "No Call";
4081 if (call->c_type != CALL_TYPE_PBX)
4083 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call is nto a pbx call.\n", ea_endpoint->ep_serial);
4084 *errstr = "No PBX Call";
4087 callpbx = (class CallPBX *)call;
4088 relation = callpbx->c_relation;
4091 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call has no relation.\n", ea_endpoint->ep_serial);
4092 *errstr = "No Call";
4095 if (!relation->next)
4097 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call has no 2nd relation.\n", ea_endpoint->ep_serial);
4098 *errstr = "No Call";
4101 if (relation->next->next)
4103 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call has more than two relations.\n", ea_endpoint->ep_serial);
4104 *errstr = "Err: Conference";
4107 if (relation->epoint_id == ea_endpoint->ep_serial)
4109 relation = relation->next;
4110 if (relation->epoint_id == ea_endpoint->ep_serial)
4112 PERROR("EPOINT(%d) SOFTWARE ERROR: both call relations are related to our endpoint.\n", ea_endpoint->ep_serial);
4113 *errstr = "Software Error";
4118 /* check remote port for external call */
4119 epoint = find_epoint_id(relation->epoint_id);
4122 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call has no 2nd endpoint.\n", ea_endpoint->ep_serial);
4123 *errstr = "No Call";
4126 if (!epoint->ep_portlist)
4128 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not port.\n", ea_endpoint->ep_serial);
4129 *errstr = "No Call";
4132 *port = find_port_id(epoint->ep_portlist->port_id);
4135 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has an none existing port.\n", ea_endpoint->ep_serial);
4136 *errstr = "No Call";
4139 if (((*port)->p_type&PORT_CLASS_mISDN_MASK)!=PORT_CLASS_mISDN_DSS1) /* port is not external isdn */
4141 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not an external port.\n", ea_endpoint->ep_serial);
4142 *errstr = "No Ext Call";
4145 if ((*port)->p_state != PORT_STATE_CONNECT)
4147 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint's port is not in connected state.\n", ea_endpoint->ep_serial);
4148 *errstr = "No Ext Connect";
4154 void EndpointAppPBX::logmessage(struct message *message)
4158 char *logtext = "unknown";
4161 if (message->flow != EPOINT_TO_PORT)
4163 PERROR("EPOINT(%d) message not of correct flow type-\n", ea_endpoint->ep_serial);
4167 switch(message->type)
4170 port = find_port_id(message->id_to);
4173 if (port->p_type == PORT_TYPE_DSS1_NT_OUT)
4175 pdss1 = (class Pdss1 *)port;
4176 printlog("%3d outgoing SETUP from %s='%s'%s%s%s%s to intern='%s' port='%d' (NT)\n",
4177 ea_endpoint->ep_serial,
4178 (message->param.setup.callerinfo.intern[0])?"intern":"extern",
4179 (message->param.setup.callerinfo.intern[0])?e_callerinfo.intern:e_callerinfo.id,
4180 (message->param.setup.callerinfo.present==INFO_PRESENT_RESTRICTED)?" anonymous":"",
4181 (message->param.setup.redirinfo.id[0])?"redirected='":"",
4182 message->param.setup.redirinfo.id,
4183 (message->param.setup.redirinfo.id[0])?"'":"",
4184 message->param.setup.dialinginfo.number,
4185 pdss1->p_m_mISDNport->portnum
4188 if (port->p_type == PORT_TYPE_DSS1_TE_OUT)
4190 pdss1 = (class Pdss1 *)port;
4191 printlog("%3d outgoing SETUP from %s='%s'%s%s%s%s to extern='%s' port='%d' (TE)\n",
4192 ea_endpoint->ep_serial,
4193 (message->param.setup.callerinfo.intern[0])?"intern":"extern",
4194 (message->param.setup.callerinfo.intern[0])?e_callerinfo.intern:e_callerinfo.id,
4195 (message->param.setup.callerinfo.present==INFO_PRESENT_RESTRICTED)?" anonymous":"",
4196 (message->param.setup.redirinfo.id[0])?"redirected='":"",
4197 message->param.setup.redirinfo.id,
4198 (message->param.setup.redirinfo.id[0])?"'":"",
4199 message->param.setup.dialinginfo.number,
4200 pdss1->p_m_mISDNport->portnum
4203 if (port->p_type == PORT_TYPE_VBOX_OUT)
4205 printlog("%3d outgoing SETUP from %s='%s'%s%s%s%s to vbox='%s'\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
4218 case MESSAGE_OVERLAP:
4219 printlog("%3d outgoing SETUP ACKNOWLEDGE\n",
4220 ea_endpoint->ep_serial
4224 case MESSAGE_PROCEEDING:
4225 printlog("%3d outgoing PROCEEDING\n",
4226 ea_endpoint->ep_serial
4230 case MESSAGE_ALERTING:
4231 printlog("%3d outgoing ALERTING\n",
4232 ea_endpoint->ep_serial
4236 case MESSAGE_CONNECT:
4237 printlog("%3d outgoing CONNECT id='%s'%s\n",
4238 ea_endpoint->ep_serial,
4239 message->param.connectinfo.id,
4240 (message->param.connectinfo.present==INFO_PRESENT_RESTRICTED)?" anonymous":""
4244 case MESSAGE_DISCONNECT:
4245 printlog("%3d outgoing DISCONNECT cause='%d' (%s) location='%d' (%s) display='%s'\n",
4246 ea_endpoint->ep_serial,
4247 message->param.disconnectinfo.cause,
4248 (message->param.disconnectinfo.cause>0 && message->param.disconnectinfo.cause<128)?isdn_cause[message->param.disconnectinfo.cause].english:"-",
4249 message->param.disconnectinfo.location,
4250 (message->param.disconnectinfo.location>=0 && message->param.disconnectinfo.location<16)?isdn_location[message->param.disconnectinfo.location].english:"-",
4251 message->param.disconnectinfo.display
4255 case MESSAGE_RELEASE:
4256 printlog("%3d outgoing RELEASE cause='%d' (%s) location='%d' (%s)\n",
4257 ea_endpoint->ep_serial,
4258 message->param.disconnectinfo.cause,
4259 (message->param.disconnectinfo.cause>0 && message->param.disconnectinfo.cause<128)?isdn_cause[message->param.disconnectinfo.cause].english:"-",
4260 message->param.disconnectinfo.location,
4261 (message->param.disconnectinfo.location>=0 && message->param.disconnectinfo.location<16)?isdn_location[message->param.disconnectinfo.location].english:"-"
4265 case MESSAGE_NOTIFY:
4266 switch(message->param.notifyinfo.notify)
4272 logtext = "USER_SUSPENDED";
4275 logtext = "BEARER_SERVICE_CHANGED";
4278 logtext = "USER_RESUMED";
4281 logtext = "CONFERENCE_ESTABLISHED";
4284 logtext = "CONFERENCE_DISCONNECTED";
4287 logtext = "OTHER_PARTY_ADDED";
4290 logtext = "ISOLATED";
4293 logtext = "REATTACHED";
4296 logtext = "OTHER_PARTY_ISOLATED";
4299 logtext = "OTHER_PARTY_REATTACHED";
4302 logtext = "OTHER_PARTY_SPLIT";
4305 logtext = "OTHER_PARTY_DISCONNECTED";
4308 logtext = "CONFERENCE_FLOATING";
4311 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
4314 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
4317 logtext = "CALL_IS_A_WAITING_CALL";
4320 logtext = "DIVERSION_ACTIVATED";
4323 logtext = "RESERVED_CT_1";
4326 logtext = "RESERVED_CT_2";
4329 logtext = "REVERSE_CHARGING";
4332 logtext = "REMOTE_HOLD";
4335 logtext = "REMOTE_RETRIEVAL";
4338 logtext = "CALL_IS_DIVERTING";
4341 SPRINT(buffer, "indicator=%d", message->param.notifyinfo.notify - 0x80);
4345 printlog("%3d outgoing NOTIFY notify='%s' id='%s'%s display='%s'\n",
4346 ea_endpoint->ep_serial,
4348 message->param.notifyinfo.id,
4349 (message->param.notifyinfo.present==INFO_PRESENT_RESTRICTED)?" anonymous":"",
4350 message->param.notifyinfo.display
4354 case MESSAGE_INFORMATION:
4355 printlog("%3d outgoing INFORMATION information='%s'\n",
4356 ea_endpoint->ep_serial,
4357 message->param.information.number
4361 case MESSAGE_FACILITY:
4362 printlog("%3d outgoing FACILITY len='%d'\n",
4363 ea_endpoint->ep_serial,
4364 message->param.facilityinfo.len
4369 printlog("%3d outgoing TONE dir='%s' name='%s'\n",
4370 ea_endpoint->ep_serial,
4371 message->param.tone.dir,
4372 message->param.tone.name
4377 PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message->type);
4381 void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cause, int location, char *display)
4383 struct message *message;
4387 if (!portlist->port_id)
4390 if (!e_connectedmode)
4392 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT);
4393 message->param.disconnectinfo.cause = cause;
4394 message->param.disconnectinfo.location = location;
4396 SCPY(message->param.disconnectinfo.display, display);
4398 SCPY(message->param.disconnectinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4401 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
4403 SCPY(message->param.notifyinfo.display, display);
4405 SCPY(message->param.notifyinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4407 message_put(message);
4408 logmessage(message);