1 /*****************************************************************************\
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
8 ** The EndpointAppPBX implements PBX4Linux **
10 \*****************************************************************************/
15 #include <sys/types.h>
24 class EndpointAppPBX *apppbx_first = NULL;
27 * EndpointAppPBX constructor
29 EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint) : EndpointApp(epoint)
31 class EndpointAppPBX **apppointer;
33 /* add application to chain */
35 apppointer = &apppbx_first;
37 apppointer = &((*apppointer)->next);
41 memset(&e_ext, 0, sizeof(struct extension));
42 e_ext.rights = 4; /* international */
43 e_ext.rxvol = e_ext.txvol = 256;
44 e_state = EPOINT_STATE_IDLE;
45 e_ext.number[0] = '\0';
46 e_extension_interface[0] = '\0';
47 memset(&e_callerinfo, 0, sizeof(struct caller_info));
48 memset(&e_dialinginfo, 0, sizeof(struct dialing_info));
49 memset(&e_connectinfo, 0, sizeof(struct connect_info));
50 memset(&e_redirinfo, 0, sizeof(struct redir_info));
51 memset(&e_capainfo, 0, sizeof(struct capa_info));
54 e_ruleset = ruleset_main;
56 e_rule = e_ruleset->rule_first;
61 e_match_to_action = NULL;
63 e_extdialing = e_dialinginfo.number;
67 // e_call_tone[0] = e_hold_tone[0] = '\0';
68 e_call_pattern /*= e_hold_pattern*/ = 0;
71 e_adminid = 0; // will be set, if call was initiated via admin socket
76 e_cbdialing[0] = '\0';
79 memset(&e_callbackinfo, 0, sizeof(struct caller_info));
86 e_password_timeout = 0;
87 e_multipoint_cause = CAUSE_NOUSER;
88 e_multipoint_location = LOCATION_PRIVATE_LOCAL;
89 e_dialing_queue[0] = '\0';
91 e_crypt_state = CM_ST_NULL;
92 e_crypt_keyengine_busy = 0;
93 e_crypt_info[0] = '\0';
96 e_tx_state = NOTIFY_STATE_ACTIVE;
97 e_rx_state = NOTIFY_STATE_ACTIVE;
98 e_call_cause = e_call_location = 0;
99 /*********************************
100 *********************************
101 ********* ATTENTION *************
102 *********************************
103 *********************************/
104 /* if you add new values, that must be initialized, also check if they must
105 * be initialized when doing callback
111 * EpointAppPBX destructor
113 EndpointAppPBX::~EndpointAppPBX(void)
115 class EndpointAppPBX *temp, **tempp;
119 tempp = &apppbx_first;
130 PERROR("error: endpoint not in endpoint's list, exitting.\n");
139 * trace header for application
141 void EndpointAppPBX::trace_header(char *name, int direction)
143 char msgtext[sizeof(trace.name)];
147 /* init trace with given values */
148 start_trace(e_serial,
150 nationalize(e_callerinfo.id, e_callerinfo.ntype),
151 e_dialinginfo.number,
161 /* set new endpoint state
163 void EndpointAppPBX::new_state(int state)
166 if (e_state != state)
168 trace_header("NEW STATE", DIRECTION_NONE);
169 add_trace("state", "old", "%s", state_name[e_state]);
170 add_trace("state", "new", "%s", state_name[state]);
179 * out==0: incomming caller id, out==1: outgoing caller id
181 void EndpointAppPBX::screen(int out, char *id, int idsize, int *type, int *present)
183 struct interface *interface;
185 interface = interface_first;
188 if (!strcmp(e_callerinfo.interface, interface->name))
192 interface = interface->next;
197 /* screen incoming caller id */
200 /* check for MSN numbers, use first MSN if no match */
202 ifmsn = interface->ifmsn;
207 if (!strcmp(ifmns->mns, id))
213 if (!ifmns && mns1) // not in list, first msn given
214 UNCPY(id, msn1, idsize);
218 /* check screen list */
220 iscreen = interface->ifscreen_out;
222 iscreen = interface->ifscreen_in;
225 if (ifcreen->match_type==-1 || ifscreen->match_type==*type)
226 if (ifcreen->match_present==-1 || ifscreen->match_present==*present)
228 if (strchr(ifcreen->match_id,'%'))
230 if (!strncmp(ifscreen->match_id, id, strchr(ifscreen->match_id,'%')-ifscreen->match_id))
234 if (!strcmp(ifscreen->match_id, id))
238 ifscreen = ifscreen->next;
240 if (ifscreen) // match
242 if (ifscren->result_type != -1)
243 *type = ifscreen->result_type;
244 if (ifscren->result_present != -1)
245 *present = ifscreen->result_present;
246 if (strchr(ifscreen->match_id,'%'))
248 SCPY(suffix, strchr(ifscreen->match_id,'%') - ifscreen->match_id + id);
249 UNCPY(id, ifscreen->result_id);
251 if (strchr(ifscreen->result_id,'%'))
253 *strchr(ifscreen->result_id,'%') = '\0';
254 UNCAT(id, suffix, idsize);
259 UNCPY(id, ifscreen->result_id, idsize);
266 /* release call and port (as specified)
268 void EndpointAppPBX::release(int release, int calllocation, int callcause, int portlocation, int portcause)
270 struct port_list *portlist;
271 struct message *message;
275 /* message to test call */
276 admin_call_response(e_adminid, ADMIN_CALL_RELEASE, "", callcause, calllocation, 0);
278 /* if a release is pending */
279 if (release==RELEASE_CALL || release==RELEASE_ALL || release==RELEASE_PORT_CALLONLY)
281 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): do pending release (callcause %d location %d)\n", ea_endpoint->ep_serial, callcause, calllocation);
282 if (ea_endpoint->ep_call_id)
284 call = find_call_id(ea_endpoint->ep_call_id);
286 call->release(ea_endpoint->ep_serial, 0, calllocation, callcause);
288 ea_endpoint->ep_call_id = 0;
291 if (release != RELEASE_PORT_CALLONLY)
294 call_release(e_hold_id, ea_endpoint->ep_serial, 1, calllocation, callcause);
299 if (release==RELEASE_ALL || release==RELEASE_PORT_CALLONLY)
301 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release (portcause %d portlocation)\n", ea_endpoint->ep_serial, portcause, portlocation);
302 while((portlist = ea_endpoint->ep_portlist))
304 if (portlist->port_id)
306 SPRINT(cause, "cause_%02x", portcause);
307 set_tone(portlist, cause);
308 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
309 message->param.disconnectinfo.cause = portcause;
310 message->param.disconnectinfo.location = portlocation;
311 message_put(message);
314 ea_endpoint->free_portlist(portlist);
317 /* if callback is enabled, call back with the given caller id */
320 /* reset some stuff */
321 new_state(EPOINT_STATE_IDLE);
322 memset(&e_connectinfo, 0, sizeof(struct connect_info));
323 memset(&e_redirinfo, 0, sizeof(struct redir_info));
324 e_start = e_stop = 0;
325 e_ruleset = ruleset_main;
327 e_rule = e_ruleset->rule_first;
329 e_action_timeout = 0;
331 e_match_to_action = NULL;
333 e_extdialing = e_dialinginfo.number;
340 e_multipoint_cause = CAUSE_NOUSER;
341 e_multipoint_location = LOCATION_PRIVATE_LOCAL;
342 e_dialing_queue[0] = '\0';
344 e_crypt_state = CM_ST_NULL;
345 e_crypt_keyengine_busy = 0;
346 e_crypt_info[0] = '\0';
350 e_tx_state = NOTIFY_STATE_ACTIVE;
351 e_rx_state = NOTIFY_STATE_ACTIVE;
352 e_call_cause = e_call_location = 0;
354 /* the caller info of the callback user */
355 memcpy(&e_callbackinfo, &e_callerinfo, sizeof(e_callbackinfo));
356 memset(&e_dialinginfo, 0, sizeof(e_dialinginfo));
357 /* create dialing by callerinfo */
358 if (e_ext.number[0] && e_extension_interface[0])
360 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to internal: %s interface %s\n", ea_endpoint->ep_serial, e_ext.number, e_extension_interface);
361 /* create callback to the current terminal */
362 SCPY(e_dialinginfo.number, e_ext.number);
363 SCPY(e_dialinginfo.interfaces, e_extension_interface);
364 e_dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
365 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
370 SCPY(e_dialinginfo.number, e_cbto);
373 /* numberrize caller id and use it to dial to the callback */
374 SCPY(e_dialinginfo.number, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype));
376 e_dialinginfo.itype = INFO_ITYPE_ISDN;
377 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
378 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to external: %s\n", ea_endpoint->ep_serial, e_dialinginfo.number);
383 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release of epoint itself.\n", ea_endpoint->ep_serial);
384 ea_endpoint->ep_use--; /* when e_lock is 0, the endpoint will be deleted */
390 /* cancel callerid if restricted, unless anon-ignore is enabled at extension or port is of type external (so called police gets caller id :)*/
391 void apply_callerid_restriction(int anon_ignore, int port_type, char *id, int *ntype, int *present, int *screen, char *voip, char *intern, char *name)
393 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");
395 /* caller id is not restricted, so we do nothing */
396 if (*present != INFO_PRESENT_RESTRICTED)
399 /* only extensions are restricted */
405 /* if we enabled anonymouse ignore */
409 /* else we remove the caller id */
413 *ntype = INFO_NTYPE_UNKNOWN;
415 // *screen = INFO_SCREEN_USER;
416 // maybe we should not make voip address anonymous
419 // maybe it's no fraud to present internal id
426 /* used display message to display callerid as available */
427 char *EndpointAppPBX::apply_callerid_display(char *id, int itype, int ntype, int present, int screen, char *voip, char *intern, char *name)
429 static char display[81];
432 char *cid = numberrize_callerinfo(id, ntype);
434 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");
445 /* NOTE: is caller is is not available for this extesion, it has been removed by apply_callerid_restriction already */
447 /* internal extension's caller id */
448 if (intern[0] && e_ext.display_int)
451 SCAT(display, intern);
454 if (itype == INFO_ITYPE_VBOX)
455 SCAT(display, "(vbox)");
457 SCAT(display, "(int)");
460 /* external caller id */
461 if (!intern[0] && !voip[0] && e_ext.display_ext)
467 if (present == INFO_PRESENT_RESTRICTED)
468 SCAT(display, "anonymous");
470 SCAT(display, "unknown");
478 if (voip[0] && e_ext.display_voip)
480 if (!display[0] && cid[0])
487 /* display if callerid is anonymouse but available due anon-ignore */
488 if (e_ext.display_anon && present==INFO_PRESENT_RESTRICTED)
491 SCAT(display, "unknown");
494 SCAT(display, " anon");
497 /* display if callerid is anonymouse but available due anon-ignore */
498 if (e_ext.display_fake && screen==INFO_SCREEN_USER && present!=INFO_PRESENT_NULL)
504 if (present == INFO_PRESENT_RESTRICTED)
505 SCAT(display, "anonymous");
507 SCAT(display, "unknown");
512 SCAT(display, " fake");
516 if (name[0] && e_ext.display_name)
518 if (!display[0] && cid[0])
529 * uses the current state to notify activity
531 void EndpointAppPBX::notify_active(void)
533 struct port_list *portlist = ea_endpoint->ep_portlist;
534 struct message *message;
539 case NOTIFY_STATE_ACTIVE:
540 /* we are already active, so we don't do anything */
543 case NOTIFY_STATE_SUSPEND:
544 notify = INFO_NOTIFY_USER_RESUMED;
547 set_tone(portlist, NULL);
548 portlist = portlist->next;
550 portlist = ea_endpoint->ep_portlist;
553 case NOTIFY_STATE_HOLD:
554 notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
557 set_tone(portlist, NULL);
558 portlist = portlist->next;
560 portlist = ea_endpoint->ep_portlist;
563 case NOTIFY_STATE_CONFERENCE:
564 notify = INFO_NOTIFY_CONFERENCE_DISCONNECTED;
567 set_tone(portlist, NULL);
568 portlist = portlist->next;
570 portlist = ea_endpoint->ep_portlist;
574 PERROR("unknown e_tx_state = %d\n", e_tx_state);
580 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
581 message->param.notifyinfo.notify = notify;
582 message_put(message);
584 portlist = portlist->next;
590 * keypad functions during call. one example to use this is to put a call on hold or start a conference
592 void EndpointAppPBX::keypad_function(char digit)
595 /* we must be in a call, in order to send messages to the call */
596 if (e_ext.number[0] == '\0')
598 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) IGNORING keypad received not from extension.\n", ea_endpoint->ep_serial);
604 /* join conference */
606 if (ea_endpoint->ep_call_id == 0)
608 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad received during connect but not during a call.\n", ea_endpoint->ep_serial);
611 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join call with call on hold\n", ea_endpoint->ep_serial);
617 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) shared key encryption selected.\n", ea_endpoint->ep_serial);
621 /* crypt key-exchange */
623 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) key exchange encryption selected.\n", ea_endpoint->ep_serial);
629 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) encryption off selected.\n", ea_endpoint->ep_serial);
634 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) unsupported keypad digit '%c'.\n", ea_endpoint->ep_serial, digit);
639 /* set tone pattern for port */
640 void EndpointAppPBX::set_tone(struct port_list *portlist, char *tone)
642 struct message *message;
647 /* store for suspended processes */
652 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no endpoint to notify tone.\n", ea_endpoint->ep_serial);
656 if (e_call_pattern /* pattern are provided */
657 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_SETUP)
658 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_OVERLAP)
659 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_IN_PROCEEDING)
660 && !(e_ext.own_alerting && e_state == EPOINT_STATE_IN_ALERTING)
661 && !(e_ext.own_cause && e_state == EPOINT_STATE_IN_DISCONNECT)
662 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_SETUP)
663 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_OVERLAP)
664 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_OUT_PROCEEDING)
665 && !(e_ext.own_alerting && e_state == EPOINT_STATE_OUT_ALERTING)
666 && !(e_ext.own_cause && e_state == EPOINT_STATE_OUT_DISCONNECT)
667 && tone[0] && !!strncmp(tone,"crypt_*",6))
669 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) tone not provided since patterns are available\n", ea_endpoint->ep_serial);
675 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_TONE);
676 SCPY(message->param.tone.dir, e_ext.tones_dir[0]?e_ext.tones_dir:options.tones_dir);
677 SCPY(message->param.tone.name, tone);
678 message_put(message);
685 * hunts an mISDNport that is available for an outgoing call
686 * if no ifname was given, any interface that is not an extension
689 static struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel)
691 struct interface *interface;
692 struct mISDNport *mISDNport;
694 interface = interface_first;
696 /* first find the given interface or, if not given, one with no extension */
701 /* check for given interface */
704 if (!strcasecmp(interface->name, ifname))
706 /* found explicit interface */
707 trace_header("CHANNEL SELECTION (found interface)", DIRECTION_NONE);
708 add_trace("interface", NULL, "%s", ifname);
715 if (!interface->extension)
717 /* found non extension */
718 trace_header("CHANNEL SELECTION (found non extension interface)", DIRECTION_NONE);
719 add_trace("interface", NULL, "%s", interface->name);
725 interface = interface->next;
728 /* see if interface has ports */
729 if (!interface->ifport)
732 trace_header("CHANNEL SELECTION (interface has no active ports, skipping)", DIRECTION_NONE);
733 add_trace("interface", NULL, "%s", interface->name);
735 interface = interface->next;
739 /* select port by algorithm */
740 ifport_start = interface->port;
742 if (interface->hunt == HUNT_ROUNDROBIN)
744 while(ifport_start->next && index<interface->hunt_next)
746 ifport_start = ifport_start->next;
749 trace_header("CHANNEL SELECTION (starting round-robin)", DIRECTION_NONE);
750 add_trace("port", NULL, "%d", ifport_start->portnum);
751 add_trace("position", NULL, "%d", index);
756 ifport = ifport_start;
759 /* see if port is available */
760 if (!ifport->mISDNport)
762 trace_header("CHANNEL SELECTION (port not available, skipping)", DIRECTION_NONE);
763 add_trace("port", NULL, "%d", ifport->portnum);
764 add_trace("position", NULL, "%d", index);
768 mISDNport = ifport->mISDNport;
770 #warning admin block auch bei incomming calls
771 #warning calls releasen, wenn port entfernt wird, geblockt wird
772 /* see if port is administratively blocked */
775 trace_header("CHANNEL SELECTION (port blocked by admin, skipping)", DIRECTION_NONE);
776 add_trace("port", NULL, "%d", ifport->portnum);
777 add_trace("position", NULL, "%d", index);
782 /* see if link is up */
783 if (mISDNport->ptp && !mISDNport->l2link)
785 trace_header("CHANNEL SELECTION (port is ptp with layer 2 down, skipping)", DIRECTION_NONE);
786 add_trace("port", NULL, "%d", ifport->portnum);
787 add_trace("position", NULL, "%d", index);
792 /* check for channel form selection list */
794 selchannel = ifport->selchannel;
797 switch(selchannel->channel)
799 case CHANNEL_FREE: /* free channel */
800 if (mISDNport->b_inuse >= mISDNport->b_num)
801 break; /* all channel in use or reserverd */
804 while(i < mISDNport->b_num)
806 if (mISDNport->b_port[i] == NULL)
808 *channel = i+1+(i>=15);
809 trace_header("CHANNEL SELECTION (selecting free channel)", DIRECTION_NONE);
810 add_trace("port", NULL, "%d", ifport->portnum);
811 add_trace("position", NULL, "%d", index);
812 add_trace("channel", NULL, "%d", *channel);
820 case CHANNEL_ANY: /* don't ask for channel */
821 if (mISDNport->b_inuse >= mISDNport->b_num)
823 break; /* all channel in use or reserverd */
825 trace_header("CHANNEL SELECTION (using 'any channel')", DIRECTION_NONE);
826 add_trace("port", NULL, "%d", ifport->portnum);
827 add_trace("position", NULL, "%d", index);
829 *channel = SEL_CHANNEL_ANY;
832 case CHANNEL_NO: /* call waiting */
833 trace_header("CHANNEL SELECTION (using 'no channel', call-waiting)", DIRECTION_NONE);
834 add_trace("port", NULL, "%d", ifport->portnum);
835 add_trace("position", NULL, "%d", index);
837 *channel = SEL_CHANNEL_NO;
841 if (selchannel->channel<1 || selchannel->channel==16)
842 break; /* invalid channels */
843 i = selchannel->channel-1-(selchannel->channel>=17);
844 if (i >= mISDNport->b_num)
845 break; /* channel not in port */
846 if (mISDNport->b_port[i] == NULL)
848 *channel = selchannel->channel;
849 trace_header("CHANNEL SELECTION (selecting given channel)", DIRECTION_NONE);
850 add_trace("port", NULL, "%d", ifport->portnum);
851 add_trace("position", NULL, "%d", index);
852 add_trace("channel", NULL, "%d", *channel);
859 break; /* found channel */
860 selchannel = selchannel->next;
863 /* if channel was found, return mISDNport and channel */
866 /* setting next port to start next time */
867 if (interface->hunt == HUNT_ROUNDROBIN)
872 interface->hunt_next = index;
878 trace_header("CHANNEL SELECTION (skipping, no channel found)", DIRECTION_NONE);
879 add_trace("port", NULL, "%d", ifport->portnum);
880 add_trace("position", NULL, "%d", index);
884 /* go next port, until all ports are checked */
886 ifport = ifport->next;
890 ifport = interface->ifport;
892 if (ifport != ifport_start)
895 return(NULL); /* no port found */
898 /* outgoing setup to port(s)
899 * ports will be created and a setup is sent if everything is ok. otherwhise
900 * the endpoint is destroyed.
902 void EndpointAppPBX::out_setup(void)
904 struct dialing_info dialinginfo;
906 // class pdss1 *pdss1;
907 struct port_list *portlist;
908 struct message *message;
910 int cause = CAUSE_RESSOURCEUNAVAIL;
913 struct mISDNport *mISDNport;
916 class EndpointAppPBX *atemp;
917 // char allowed_ports[256];
921 char ifname[sizeof(e_ext.interfaces)],
923 struct port_settings port_settings;
926 /* create settings for creating port */
927 memset(&port_settings, 0, sizeof(port_settings));
929 SCPY(port_settings.tones_dir, e_ext.tones_dir);
931 SCPY(port_settings.tones_dir, options.tones_dir);
932 port_settings.tout_setup = e_ext.tout_setup;
933 port_settings.tout_dialing = e_ext.tout_dialing;
934 port_settings.tout_proceeding = e_ext.tout_proceeding;
935 port_settings.tout_alerting = e_ext.tout_alerting;
936 port_settings.tout_disconnect = e_ext.tout_disconnect;
937 // port_settings.tout_hold = e_ext.tout_hold;
938 // port_settings.tout_park = e_ext.tout_park;
939 port_settings.no_seconds = e_ext.no_seconds;
941 /* 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 */
943 /* check what dialinginfo.itype we got */
944 switch(e_dialinginfo.itype)
946 /* *********************** call to extension or vbox */
947 case INFO_ITYPE_ISDN_EXTENSION:
948 /* check if we deny incoming calls when we use an extension */
949 if (e_ext.noknocking)
951 atemp = apppbx_first;
955 if (!strcmp(atemp->e_ext.number, e_ext.number))
961 PERROR("EPOINT(%d) noknocking and currently a call\n", ea_endpoint->ep_serial);
962 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYSPE_ call, port */
963 return; /* must exit here */
966 /* FALL THROUGH !!!! */
967 case INFO_ITYPE_VBOX:
968 /* get dialed extension's info */
969 // SCPY(exten, e_dialinginfo.number);
970 // if (strchr(exten, ','))
971 // *strchr(exten, ',') = '\0';
972 // if (!read_extension(&e_ext, exten))
973 if (!read_extension(&e_ext, e_dialinginfo.number))
975 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) extension %s not configured\n", ea_endpoint->ep_serial, e_dialinginfo.number);
976 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
977 return; /* must exit here */
980 if (e_dialinginfo.itype == INFO_ITYPE_VBOX)
982 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing directly to VBOX\n", ea_endpoint->ep_serial);
987 /* string from unconditional call forward (cfu) */
991 /* present to forwarded party */
992 if (e_ext.anon_ignore && e_callerinfo.id[0])
994 e_callerinfo.present = INFO_PRESENT_ALLOWED;
996 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
1000 /* string from busy call forward (cfb) */
1004 class EndpointAppPBX *checkapp = apppbx_first;
1007 if (checkapp != this) /* any other endpoint except our own */
1009 if (!strcmp(checkapp->e_ext.number, e_ext.number))
1011 /* present to forwarded party */
1012 if (e_ext.anon_ignore && e_callerinfo.id[0])
1014 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1016 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
1020 checkapp = checkapp->next;
1024 /* string from no-response call forward (cfnr) */
1028 /* when cfnr is done, out_setup() will setup the call */
1031 /* present to forwarded party */
1032 if (e_ext.anon_ignore && e_callerinfo.id[0])
1034 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1038 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
1040 e_cfnr_release = now + e_ext.cfnr_delay;
1041 e_cfnr_call = now + e_ext.cfnr_delay + 1; /* call one second after release */
1042 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);
1046 /* call to all internal interfaces */
1047 p = e_ext.interfaces;
1048 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) generating multiple calls for extension %s to interfaces %s\n", ea_endpoint->ep_serial, e_dialinginfo.number, p);
1052 while(*p!=',' && *p!='\0')
1054 SCCAT(ifname, *p++);
1057 /* found interface */
1058 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
1059 /* hunt for mISDNport and create Port */
1060 mISDNport = hunt_port(ifname, &channel);
1063 trace_header("INTERFACE (not found or busy)", DIRECTION_NONE);
1064 add_trace("interface", NULL, "%s", ifname);
1068 /* creating INTERNAL port */
1069 SPRINT(portname, "%s-%d-out", mISDNport->interface_name, mISDNport->portnum);
1070 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport.channel_force);
1073 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port '%s' failed to create\n", ea_endpoint->ep_serial, mISDNport->interface_name);
1074 goto check_anycall_intern;
1076 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
1077 memset(&dialinginfo, 0, sizeof(dialinginfo));
1078 SCPY(dialinginfo.number, e_dialinginfo.number);
1079 dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
1080 dialinginfo.ntype = e_dialinginfo.ntype;
1081 /* create port_list relation */
1082 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->is_earlyb);
1085 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1087 goto check_anycall_intern;
1089 /* directory.list */
1090 if (e_callerinfo.id[0] && (e_ext.centrex || e_ext.display_name))
1092 dirname = parse_directory(e_callerinfo.id, e_callerinfo.ntype);
1094 SCPY(e_callerinfo.name, dirname);
1096 // dss1 = (class Pdss1 *)port;
1098 //printf("INTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.number);
1099 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1100 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1101 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1102 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1103 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1104 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1105 //terminal if (e_dialinginfo.number)
1106 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.number);
1107 /* handle restricted caller ids */
1108 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);
1109 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);
1110 /* display callerid if desired for extension */
1111 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));
1112 //printf("\n\ndisplay = %s\n\n\n",message->param.setup.callerinfo.display);
1113 /* use cnip, if enabld */
1115 message->param.setup.callerinfo.name[0] = '\0';
1116 /* screen clip if prefix is required */
1117 if (message->param.setup.callerinfo.id[0] && e_ext.clip_prefix[0])
1119 SCPY(message->param.setup.callerinfo.id, e_ext.clip_prefix);
1120 SCAT(message->param.setup.callerinfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype));
1121 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1123 /* use internal caller id */
1124 if (e_callerinfo.intern[0] && (message->param.setup.callerinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
1126 SCPY(message->param.setup.callerinfo.id, e_callerinfo.intern);
1127 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1129 message_put(message);
1130 logmessage(message);
1134 /* string from parallel call forward (cfp) */
1138 if (e_ext.anon_ignore && e_callerinfo.id[0])
1140 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1144 vbox_only: /* entry point for answering machine only */
1145 cfu_only: /* entry point for cfu */
1146 cfb_only: /* entry point for cfb */
1147 cfnr_only: /* entry point for cfnr */
1148 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call extension %s for external destiantion(s) '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.number, p);
1152 /* only if vbox should be dialed, and terminal is given */
1154 if (!strcmp(p, "vbox") && e_ext.number[0])
1156 /* go to the end of p */
1159 /* answering vbox call */
1160 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) answering machine\n", ea_endpoint->ep_serial);
1162 if (!(port = new VBoxPort(PORT_TYPE_VBOX_OUT, &port_settings)))
1164 PERROR("EPOINT(%d) no mem for port\n", ea_endpoint->ep_serial);
1167 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocated port %s\n", ea_endpoint->ep_serial, port->p_name);
1168 UCPY(cfp, e_ext.number); /* cfp or any other direct forward/vbox */
1172 while(*p!=',' && *p!='\0')
1178 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cfp external %s\n", ea_endpoint->ep_serial, cfp);
1179 /* hunt for mISDNport and create Port */
1180 mISDNport = mISDNport_first;
1184 /* check for external or given interface */
1185 if (((!e_dialinginfo.interfaces[0])&&mISDNport->iftype==IF_EXTERN) || !strcmp(mISDNport->interface_name, e_dialinginfo.interfaces))
1187 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) interface '%s' found\n", ea_endpoint->ep_serial, mISDNport->interface_name);
1188 cause = CAUSE_NOCHANNEL; /* when failing: out of channels */
1189 /* if PTP, skip all down links */
1190 if (mISDNport->ptp && !mISDNport->l2link)
1192 trace_header("INTERFACE (layer 2 is down)", DIRECTION_NONE);
1193 add_trace("interface", NULL, "%s", mISDNport->interface_name);
1195 mISDNport = mISDNport->next;
1198 /* if no channel is available */
1199 if (mISDNport->multilink || !mISDNport->ntmode || mISDNport->ptp)
1203 ii = mISDNport->b_num;
1206 if (mISDNport->b_state[i])
1210 if (use >= mISDNport->b_num)
1212 trace_header("INTERFACE (no free channel)", DIRECTION_NONE);
1213 add_trace("interface", NULL, "%s", mISDNport->interface_name);
1215 mISDNport = mISDNport->next;
1219 /* found interface */
1220 trace_header("INTERFACE (found)", DIRECTION_NONE);
1221 add_trace("interface", NULL, "%s", mISDNport->interface_name);
1225 mISDNport = mISDNport->next;
1229 /* creating EXTERNAL port*/
1230 SPRINT(portname, "%s-%d-out", mISDNport->interface_name, mISDNport->portnum);
1231 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings);
1232 earlyb = mISDNport->is_earlyb;
1236 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1237 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1243 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port found or created, which is idle.\n", ea_endpoint->ep_serial);
1244 goto check_anycall_intern;
1246 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found or created port %s\n", ea_endpoint->ep_serial, port->p_name);
1247 memset(&dialinginfo, 0, sizeof(dialinginfo));
1248 SCPY(dialinginfo.number, cfp);
1249 dialinginfo.itype = INFO_ITYPE_EXTERN;
1250 dialinginfo.ntype = e_dialinginfo.ntype;
1251 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
1254 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1256 goto check_anycall_intern;
1258 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.number);
1259 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1260 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1261 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1262 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1263 /* if clip is hidden */
1264 if (e_ext.clip==CLIP_HIDE && port->p_type!=PORT_TYPE_VBOX_OUT)
1266 SCPY(message->param.setup.callerinfo.id, e_ext.callerid);
1267 SCPY(message->param.setup.callerinfo.intern, e_ext.number);
1268 message->param.setup.callerinfo.ntype = e_ext.callerid_type;
1269 message->param.setup.callerinfo.present = e_ext.callerid_present;
1271 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1272 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1273 //terminal if (e_dialinginfo.number)
1274 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.number);
1275 /* handle restricted caller ids */
1276 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);
1277 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);
1278 /* display callerid if desired for extension */
1279 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));
1280 message_put(message);
1281 logmessage(message);
1285 check_anycall_intern:
1286 /* now we have all ports created */
1289 trace_header("INTERFACE (no extension's interface)", DIRECTION_NONE);
1291 if (!ea_endpoint->ep_call_id)
1293 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
1294 return; /* must exit here */
1298 /* *********************** external call */
1300 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.number);
1301 /* call to extenal interfaces */
1302 p = e_dialinginfo.number;
1306 while(*p!=',' && *p!='\0')
1307 SCCAT(number, *p++);
1311 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");
1312 /* hunt for mISDNport and create Port */
1313 mISDNport = mISDNport_first;
1317 /* check for external or given interface */
1318 if ((!e_dialinginfo.interfaces[0]&&mISDNport->iftype==IF_EXTERN) || !strcmp(mISDNport->interface_name, e_dialinginfo.interfaces))
1320 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) interface '%s' found\n", ea_endpoint->ep_serial, mISDNport->interface_name);
1321 cause = CAUSE_NOCHANNEL; /* when failing: out of channels */
1322 /* if PTP, skip all down links */
1323 if (mISDNport->ptp && !mISDNport->l2link)
1325 trace_header("INTERFACE (layer 2 is down)", DIRECTION_NONE);
1326 add_trace("interface", NULL, "%s", mISDNport->interface_name);
1328 mISDNport = mISDNport->next;
1331 /* if no channel is available */
1332 if (mISDNport->multilink || !mISDNport->ntmode || mISDNport->ptp)
1336 ii = mISDNport->b_num;
1339 if (mISDNport->b_state[i])
1343 if (use >= mISDNport->b_num)
1345 trace_header("INTERFACE (no free channel)", DIRECTION_NONE);
1346 add_trace("interface", NULL, "%s", mISDNport->interface_name);
1348 mISDNport = mISDNport->next;
1352 /* found interface */
1353 trace_header("INTERFACE (found)", DIRECTION_NONE);
1354 add_trace("interface", NULL, "%s", mISDNport->interface_name);
1358 mISDNport = mISDNport->next;
1362 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1363 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1365 goto check_anycall_extern;
1367 /* creating EXTERNAL port*/
1368 SPRINT(portname, "%s-%d-out", mISDNport->interface_name, mISDNport->portnum);
1369 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings);
1372 PERROR("EPOINT(%d) no memory for external port, exitting\n", ea_endpoint->ep_serial);
1375 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
1376 memset(&dialinginfo, 0, sizeof(dialinginfo));
1377 SCPY(dialinginfo.number, number);
1378 dialinginfo.itype = INFO_ITYPE_EXTERN;
1379 dialinginfo.ntype = e_dialinginfo.ntype;
1380 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->is_earlyb);
1383 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1385 goto check_anycall_extern;
1387 // dss1 = (class Pdss1 *)port;
1388 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.number);
1389 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1390 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1391 SCPY(message->param.setup.dialinginfo.number, number);
1392 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1393 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1394 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1395 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1396 //terminal if (e_dialinginfo.number)
1397 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.number);
1398 /* handle restricted caller ids */
1399 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);
1400 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);
1401 /* display callerid if desired for extension */
1402 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));
1403 message_put(message);
1404 logmessage(message);
1408 check_anycall_extern:
1409 /* now we have all ports created */
1412 trace_header("INTERFACE (no free ports found)", DIRECTION_NONE);
1414 if (!ea_endpoint->ep_call_id)
1416 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
1417 return; /* must exit here */
1425 /* handler for endpoint
1429 int EndpointAppPBX::handler(void)
1431 if (e_crypt_state!=CM_ST_NULL)
1436 /* process answering machine (play) handling */
1439 if (e_action->index == ACTION_VBOX_PLAY)
1442 /* process action timeout */
1443 if (e_action_timeout)
1444 if (now_d >= e_action_timeout)
1446 if (e_state!=EPOINT_STATE_CONNECT)
1449 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current action timed out.\n", ea_endpoint->ep_serial);
1450 e_multipoint_cause = CAUSE_NOUSER;
1451 e_multipoint_location = LOCATION_PRIVATE_LOCAL;
1452 new_state(EPOINT_STATE_IN_OVERLAP);
1455 return(1); /* we must exit, because our endpoint might be gone */
1457 e_action_timeout = 0;
1460 /* process action timeout */
1461 if (e_match_timeout)
1462 if (now_d >= e_match_timeout)
1465 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we got a match timeout.\n", ea_endpoint->ep_serial);
1467 return(1); /* we must exit, because our endpoint might be gone */
1472 /* process redialing (epoint redials to port) */
1475 if (now_d >= e_redial)
1478 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial.\n", ea_endpoint->ep_serial);
1480 new_state(EPOINT_STATE_OUT_SETUP);
1481 /* call special setup routine */
1488 /* process powerdialing (epoint redials to epoint) */
1489 if (e_powerdialing > 0)
1491 if (now_d >= e_powerdialing)
1493 e_powerdialing = -1; /* leave power dialing on */
1494 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial of powerdial.\n", ea_endpoint->ep_serial);
1497 e_ruleset = ruleset_main;
1499 e_rule = e_ruleset->rule_first;
1501 new_state(EPOINT_STATE_IN_OVERLAP);
1507 /* process call forward no response */
1510 struct port_list *portlist;
1511 struct message *message;
1513 if (now >= e_cfnr_release)
1515 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-no-response time has expired, hanging up.\n", ea_endpoint->ep_serial);
1518 /* release all ports */
1519 while((portlist = ea_endpoint->ep_portlist))
1521 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1522 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
1523 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1524 message_put(message);
1525 logmessage(message);
1526 ea_endpoint->free_portlist(portlist);
1529 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
1530 message->param.channel = CHANNEL_STATE_HOLD;
1531 message_put(message);
1532 /* indicate no patterns */
1533 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_NOPATTERN);
1534 message_put(message);
1535 /* set setup state, since we have no response from the new call */
1536 new_state(EPOINT_STATE_OUT_SETUP);
1541 if (now >= e_cfnr_call)
1543 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-busy time has expired, calling the forwarded number: %s.\n", ea_endpoint->ep_serial, e_ext.cfnr);
1549 /* handle connection to user */
1550 if (e_state == EPOINT_STATE_IDLE)
1552 /* epoint is idle, check callback */
1554 if (now_d >= e_callback)
1556 e_callback = 0; /* done with callback */
1557 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting callback.\n", ea_endpoint->ep_serial);
1558 new_state(EPOINT_STATE_OUT_SETUP);
1564 /* check for password timeout */
1566 if (e_action->index==ACTION_PASSWORD || e_action->index==ACTION_PASSWORD_WRITE)
1568 struct port_list *portlist;
1570 if (now >= e_password_timeout)
1572 e_ruleset = ruleset_main;
1574 e_rule = e_ruleset->rule_first;
1576 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) password timeout %s\n", ea_endpoint->ep_serial, e_extdialing);
1577 trace_header("PASSWORD timeout", DIRECTION_NONE);
1579 e_connectedmode = 0;
1581 new_state(EPOINT_STATE_OUT_DISCONNECT);
1582 portlist = ea_endpoint->ep_portlist;
1585 message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
1586 set_tone(portlist, "cause_10");
1596 /* doing a hookflash */
1597 void EndpointAppPBX::hookflash(void)
1601 /* be sure that we are active */
1603 e_tx_state = NOTIFY_STATE_ACTIVE;
1605 trace_header("HOOKFLASH DTMF", DIRECTION_NONE);
1607 if (ea_endpoint->ep_use > 1)
1609 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot hooflash while child process is running.\n", ea_endpoint->ep_serial);
1612 /* dialtone after pressing the hash key */
1613 process_hangup(e_call_cause, e_call_location);
1614 e_multipoint_cause = CAUSE_NOUSER;
1615 e_multipoint_location = LOCATION_PRIVATE_LOCAL;
1616 port = find_port_id(ea_endpoint->ep_portlist->port_id);
1619 port->set_echotest(0);
1621 if (ea_endpoint->ep_call_id)
1623 release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
1625 e_ruleset = ruleset_main;
1627 e_rule = e_ruleset->rule_first;
1629 new_state(EPOINT_STATE_IN_OVERLAP);
1630 e_connectedmode = 1;
1631 SCPY(e_dialinginfo.number, e_ext.prefix);
1632 e_extdialing = e_dialinginfo.number;
1634 if (e_dialinginfo.number[0])
1636 set_tone(ea_endpoint->ep_portlist, "dialing");
1640 set_tone(ea_endpoint->ep_portlist, "dialpbx");
1647 /* messages from port
1649 /* port MESSAGE_SETUP */
1650 void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, union parameter *param)
1652 struct message *message;
1655 char extension1[32];
1657 int writeext; /* flags need to write extension after modification */
1660 portlist->port_type = param->setup.port_type;
1661 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
1662 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
1663 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
1664 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
1665 e_dtmf = param->setup.dtmf;
1667 /* screen by interface */
1668 if (e_callerinfo.interface[0])
1670 /* screen incoming caller id */
1671 screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present);
1673 colp, outclip, outcolp
1675 /* process extension */
1676 if (e_callerinfo.itype == INFO_ITYPE_INTERN)
1678 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is extension\n", ea_endpoint->ep_serial);
1679 /* port makes call from extension */
1680 SCPY(e_callerinfo.intern, e_callerinfo.id);
1681 SCPY(e_ext.number, e_callerinfo.intern);
1682 SCPY(e_extension_interface, e_callerinfo.interface);
1685 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is external or voip\n", ea_endpoint->ep_serial);
1687 trace_header("SETUP", DIRECTION_IN);
1688 if (e_callerinfo.intern[0])
1689 add_trace("extension", NULL, "%s", e_callerinfo.intern);
1690 add_trace("caller id", "number", "%s", numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype));
1691 if (e_callerinfo.present == INFO_PRESENT_RESTRICTED)
1692 add_trace("caller id", "present", "restricted");
1693 if (e_redirinfo.id[0])
1695 add_trace("redir'ing", "number", "%s", numberrize_callerinfo(e_redirinfo.id, e_redirinfo.ntype));
1696 if (e_redirinfo.present == INFO_PRESENT_RESTRICTED)
1697 add_trace("redir'ing", "present", "restricted");
1699 if (e_dialinginfo.number)
1700 add_trace("dialing", "number", "%s", e_dialinginfo.number));
1703 if (e_callerinfo.itype == INFO_ITYPE_INTERN)
1705 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1707 /* get extension's info about caller */
1708 if (!read_extension(&e_ext, e_ext.number))
1710 /* extension doesn't exist */
1711 trace_header("EXTENSION (not created)", DIRECTION_IN);
1712 add_trace("extension", NULL, "%s", e_ext.number);
1714 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
1715 new_state(EPOINT_STATE_OUT_DISCONNECT);
1716 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
1717 e_ext.number[0] = '\0'; /* no terminal */
1722 /* put prefix (next) in front of e_dialinginfo.number */
1725 SPRINT(buffer, "%s%s", e_ext.next, e_dialinginfo.number);
1726 SCPY(e_dialinginfo.number, buffer);
1727 e_ext.next[0] = '\0';
1729 } else if (e_ext.prefix[0])
1731 SPRINT(buffer, "%s%s", e_ext.prefix, e_dialinginfo.number);
1732 SCPY(e_dialinginfo.number, buffer);
1735 /* screen caller id */
1736 e_callerinfo.screen = INFO_SCREEN_NETWORK;
1738 SCPY(e_callerinfo.name, e_ext.name);
1739 /* use caller id (or if exist: id_next_call) for this call */
1740 if (e_ext.id_next_call_present >= 0)
1742 SCPY(e_callerinfo.id, e_ext.id_next_call);
1743 /* if we restrict the pesentation */
1744 if (e_ext.id_next_call_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1745 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1746 else e_callerinfo.present = e_ext.id_next_call_present;
1747 e_callerinfo.ntype = e_ext.id_next_call_type;
1748 e_ext.id_next_call_present = -1;
1752 SCPY(e_callerinfo.id, e_ext.callerid);
1753 /* if we restrict the pesentation */
1754 if (e_ext.callerid_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1755 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1756 else e_callerinfo.present = e_ext.callerid_present;
1757 e_callerinfo.ntype = e_ext.callerid_type;
1760 /* extension is written */
1762 write_extension(&e_ext, e_ext.number);
1764 /* set volume of rx and tx */
1765 if (param->setup.callerinfo.itype == INFO_ITYPE_INTERN)
1766 if (e_ext.txvol!=256 || e_ext.rxvol!=256)
1768 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
1769 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
1770 message->param.mISDNsignal.rxvol = e_ext.txvol;
1771 message->param.mISDNsignal.txvol = e_ext.rxvol;
1772 message_put(message);
1775 /* start recording if enabled */
1776 if (e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO))
1778 /* check if we are a terminal */
1779 if (e_ext.number[0] == '\0')
1780 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
1783 port = find_port_id(portlist->port_id);
1785 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
1790 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from external port\n", ea_endpoint->ep_serial);
1791 /* no terminal identification */
1792 e_ext.number[0] = '\0';
1793 e_extension_interface[0] = '\0';
1794 memset(&e_ext, 0, sizeof(e_ext));
1795 e_ext.rights = 4; /* right to dial internat */
1799 e_ruleset = ruleset_main;
1801 e_rule = e_ruleset->rule_first;
1803 e_extdialing = e_dialinginfo.number;
1804 new_state(EPOINT_STATE_IN_SETUP);
1805 if (e_dialinginfo.number[0])
1807 set_tone(portlist, "dialing");
1810 if (e_ext.number[0])
1811 set_tone(portlist, "dialpbx");
1813 set_tone(portlist, "dialtone");
1816 if (e_state == EPOINT_STATE_IN_SETUP)
1818 /* request MORE info, if not already at higher state */
1819 new_state(EPOINT_STATE_IN_OVERLAP);
1820 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_OVERLAP);
1821 message_put(message);
1822 logmessage(message);
1826 /* port MESSAGE_INFORMATION */
1827 void EndpointAppPBX::port_information(struct port_list *portlist, int message_type, union parameter *param)
1829 trace_header("INFORMATION", DIRECTION_IN);
1830 add_trace("dialing", NULL, "%s", param->information.number);
1831 if (param->information.sending_complete)
1832 add_trace("complete", NULL, NULL);
1836 /* turn off dtmf detection, in case dtmf is sent with keypad information */
1839 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) received dialing information, so dtmf is now disabled, to prevent double detection by keypad+dtmf.\n", ea_endpoint->ep_serial, param->information.number, e_ext.number, e_callerinfo.id);
1843 /* if vbox_play is done, the information are just used as they come */
1845 if (e_action->index == ACTION_VBOX_PLAY)
1847 /* concat dialing string */
1848 SCAT(e_dialinginfo.number, param->information.number);
1853 /* keypad when disconnect but in connected mode */
1854 if (e_state==EPOINT_STATE_OUT_DISCONNECT && e_connectedmode)
1856 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received after disconnect: %s.\n", ea_endpoint->ep_serial, param->information.number);
1857 /* processing keypad function */
1858 if (param->information.number[0] == '0')
1865 /* keypad when connected */
1866 if (e_state == EPOINT_STATE_CONNECT && e_ext.keypad)
1868 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.number);
1869 /* processing keypad function */
1870 if (param->information.number[0] == '0')
1874 if (param->information.number[0])
1875 keypad_function(param->information.number[0]);
1878 if (e_state != EPOINT_STATE_IN_OVERLAP)
1880 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in overlap, or connect state.\n", ea_endpoint->ep_serial);
1883 if (!param->information.number[0])
1885 if (e_dialinginfo.number[0]=='\0' && !e_action)
1887 set_tone(portlist, "dialing");
1890 if (e_action->index==ACTION_OUTDIAL
1891 || e_action->index==ACTION_EXTERNAL)
1894 set_tone(portlist, "dialing");
1895 else if (!e_extdialing[0])
1896 set_tone(portlist, "dialing");
1898 /* concat dialing string */
1899 SCAT(e_dialinginfo.number, param->information.number);
1903 /* port MESSAGE_DTMF */
1904 void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
1906 trace_header("DTMF", DIRECTION_IN);
1907 add_trace("digit", NULL, "%c", param->dtmf);
1909 /* only if dtmf detection is enabled */
1912 PDEBUG(DEBUG_EPOINT, "dtmf detection is disabled\n");
1917 NOTE: vbox is now handled due to overlap state
1918 /* if vbox_play is done, the dtmf digits are just used as they come */
1920 if (e_action->index == ACTION_VBOX_PLAY)
1922 /* concat dialing string */
1923 if (strlen(e_dialinginfo.number)+1 < sizeof(e_dialinginfo.number))
1925 e_dialinginfo.number[strlen(e_dialinginfo.number)+1] = '\0';
1926 e_dialinginfo.number[strlen(e_dialinginfo.number)] = param->dtmf;
1929 /* continue to process *X# sequences */
1933 /* check for *X# sequence */
1934 if (e_state == EPOINT_STATE_CONNECT)
1936 if (e_dtmf_time+3 < now)
1938 /* the last digit was too far in the past to be a sequence */
1939 if (param->dtmf == '*')
1940 /* only start is allowed in the sequence */
1946 /* we have a sequence of digits, see what we got */
1947 if (param->dtmf == '*')
1949 else if (param->dtmf>='0' && param->dtmf<='9')
1951 /* we need to have a star before we receive the digit of the sequence */
1952 if (e_dtmf_last == '*')
1953 e_dtmf_last = param->dtmf;
1954 } else if (param->dtmf == '#')
1957 if (e_dtmf_last>='0' && e_dtmf_last<='9')
1959 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf sequence *%c# detected.\n", ea_endpoint->ep_serial, e_dtmf_last);
1960 if (e_dtmf_last == '0')
1965 /* processing keypad function */
1967 keypad_function(e_dtmf_last);
1973 /* set last time of dtmf */
1978 /* check for ## hookflash during dialing */
1980 if (e_action->index==ACTION_PASSWORD
1981 || e_action->index==ACTION_PASSWORD_WRITE)
1983 if (param->dtmf=='#') /* current digit is '#' */
1985 if (e_state==EPOINT_STATE_IN_DISCONNECT
1986 || (e_state!=EPOINT_STATE_CONNECT && e_dtmf_time+3>=now && e_dtmf_last=='#')) /* when disconnected, just #. when dialing, ##. */
2003 /* dialing using dtmf digit */
2004 if (e_state==EPOINT_STATE_IN_OVERLAP)// && e_state==e_connectedmode)
2006 if (e_dialinginfo.number[0]=='\0' && !e_action)
2008 set_tone(portlist, "dialing");
2010 /* concat dialing string */
2011 if (strlen(e_dialinginfo.number)+1 < sizeof(e_dialinginfo.number))
2013 e_dialinginfo.number[strlen(e_dialinginfo.number)+1] = '\0';
2014 e_dialinginfo.number[strlen(e_dialinginfo.number)] = param->dtmf;
2020 /* port MESSAGE_CRYPT */
2021 void EndpointAppPBX::port_crypt(struct port_list *portlist, int message_type, union parameter *param)
2023 /* send crypt response to cryptman */
2024 if (param->crypt.type == CR_MESSAGE_IND)
2025 cryptman_msg2man(param->crypt.data, param->crypt.len);
2027 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2030 /* port MESSAGE_OVERLAP */
2031 void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, union parameter *param)
2033 struct message *message;
2035 /* signal to call tool */
2036 admin_call_response(e_adminid, ADMIN_CALL_SETUP_ACK, "", 0, 0, 0);
2038 trace_header("SETUP ACKNOWLEDGE", DIRECTION_IN);
2040 if (e_dialing_queue[0] && portlist)
2042 /* send what we have not dialed yet, because we had no setup complete */
2043 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing pending digits: '%s'\n", ea_endpoint->ep_serial, e_dialing_queue);
2044 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2045 SCPY(message->param.information.number, e_dialing_queue);
2046 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
2047 message_put(message);
2048 logmessage(message);
2049 e_dialing_queue[0] = '\0';
2051 /* check if pattern is available */
2052 if (!ea_endpoint->ep_portlist->next && portlist->earlyb) /* one port_list relation and tones available */
2054 /* indicate patterns */
2055 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_PATTERN);
2056 message_put(message);
2058 /* connect audio, if not already */
2059 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2060 message->param.channel = CHANNEL_STATE_CONNECT;
2061 message_put(message);
2064 /* indicate no patterns */
2065 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_NOPATTERN);
2066 message_put(message);
2068 /* disconnect audio, if not already */
2069 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2070 message->param.channel = CHANNEL_STATE_HOLD;
2071 message_put(message);
2073 new_state(EPOINT_STATE_OUT_OVERLAP);
2074 /* if we are in a call */
2075 if (ea_endpoint->ep_call_id)
2077 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
2078 memcpy(&message->param, param, sizeof(union parameter));
2079 message_put(message);
2083 /* port MESSAGE_PROCEEDING */
2084 void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_type, union parameter *param)
2086 struct message *message;
2088 /* signal to call tool */
2089 admin_call_response(e_adminid, ADMIN_CALL_PROCEEDING, "", 0, 0, 0);
2091 trace_header("PROCEEDING", DIRECTION_IN);
2093 e_state = EPOINT_STATE_OUT_PROCEEDING;
2094 /* check if pattern is availatle */
2095 if (!ea_endpoint->ep_portlist->next && (portlist->earlyb || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
2097 /* indicate patterns */
2098 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_PATTERN);
2099 message_put(message);
2101 /* connect audio, if not already */
2102 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2103 message->param.channel = CHANNEL_STATE_CONNECT;
2104 message_put(message);
2107 /* indicate no patterns */
2108 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_NOPATTERN);
2109 message_put(message);
2111 /* disconnect audio, if not already */
2112 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2113 message->param.channel = CHANNEL_STATE_HOLD;
2114 message_put(message);
2116 /* if we are in a call */
2117 if (ea_endpoint->ep_call_id)
2119 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
2120 memcpy(&message->param, param, sizeof(union parameter));
2121 message_put(message);
2125 /* port MESSAGE_ALERTING */
2126 void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type, union parameter *param)
2128 struct message *message;
2130 /* signal to call tool */
2131 admin_call_response(e_adminid, ADMIN_CALL_ALERTING, "", 0, 0, 0);
2133 trace_header("ALERTING", DIRECTION_IN);
2135 new_state(EPOINT_STATE_OUT_ALERTING);
2136 /* check if pattern is available */
2137 if (!ea_endpoint->ep_portlist->next && (portlist->earlyb || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
2139 /* indicate patterns */
2140 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_PATTERN);
2141 message_put(message);
2143 /* connect audio, if not already */
2144 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2145 message->param.channel = CHANNEL_STATE_CONNECT;
2146 message_put(message);
2149 /* indicate no patterns */
2150 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_NOPATTERN);
2151 message_put(message);
2153 /* disconnect audio, if not already */
2154 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2155 message->param.channel = CHANNEL_STATE_HOLD;
2156 message_put(message);
2158 /* if we are in a call */
2159 if (ea_endpoint->ep_call_id)
2161 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
2162 memcpy(&message->param, param, sizeof(union parameter));
2163 message_put(message);
2167 /* port MESSAGE_CONNECT */
2168 void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, union parameter *param)
2170 struct message *message;
2172 unsigned long port_id = portlist->port_id;
2173 struct port_list *tportlist;
2176 /* signal to call tool */
2177 admin_call_response(e_adminid, ADMIN_CALL_CONNECT, numberrize_callerinfo(param->connectinfo.id,param->connectinfo.ntype), 0, 0, 0);
2179 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_connectinfo));
2180 trace_header("CONNECT", DIRECTION_IN);
2181 if (e_connectinfo.intern[0])
2182 add_trace("extension", NULL, "%s", e_connectinfo.intern);
2183 add_trace("connect id", "number", "%s", numberrize_callerinfo(e_connectinfo.id, e_connectinfo.ntype));
2184 if (e_connectinfo.present == INFO_PRESENT_RESTRICTED)
2185 add_trace("connect id", "present", "restricted");
2187 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (start)\n", ea_endpoint->ep_serial);
2188 while(ea_endpoint->ep_portlist->next) /* as long as we have at least two ports */
2190 tportlist = ea_endpoint->ep_portlist;
2191 if (tportlist->port_id == port_id) /* if the first portlist is the calling one, the second must be a different one */
2192 tportlist = tportlist->next;
2193 if (tportlist->port_id == port_id)
2195 PERROR("EPOINT(%d) software error: this should not happen since the portlist list must not have two links to the same port - exitting.\n");
2198 message = message_create(ea_endpoint->ep_serial, tportlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2199 message->param.disconnectinfo.cause = 26; /* non selected user clearing */
2200 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2201 message_put(message);
2202 logmessage(message);
2203 ea_endpoint->free_portlist(tportlist);
2205 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (end)\n", ea_endpoint->ep_serial);
2209 /* screen by interface */
2210 if (e_callerinfo.interface[0])
2212 /* screen incoming caller id */
2213 screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present);
2216 /* screen connected name */
2218 SCPY(e_connectinfo.name, e_ext.name);
2220 /* add internal id to colp */
2221 SCPY(e_connectinfo.intern, e_ext.number);
2223 /* we store the connected port number */
2224 SCPY(e_extension_interface, e_connectinfo.interfaces);
2226 /* for internal and am calls, we get the extension's id */
2227 if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE)
2229 SCPY(e_connectinfo.id, e_ext.callerid);
2230 SCPY(e_connectinfo.intern, e_ext.number);
2231 e_connectinfo.itype = INFO_ITYPE_INTERN;
2232 e_connectinfo.ntype = e_ext.callerid_type;
2233 e_connectinfo.present = e_ext.callerid_present;
2235 if (portlist->port_type==PORT_TYPE_VBOX_OUT)
2237 e_connectinfo.itype = INFO_ITYPE_VBOX;
2238 e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2241 new_state(EPOINT_STATE_CONNECT);
2243 /* set volume of rx and tx */
2244 if (e_ext.txvol!=256 || e_ext.rxvol!=256)
2246 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2247 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2248 message->param.mISDNsignal.rxvol = e_ext.txvol;
2249 message->param.mISDNsignal.txvol = e_ext.rxvol;
2250 message_put(message);
2253 e_cfnr_call = e_cfnr_release = 0;
2254 if (e_ext.number[0])
2255 e_dtmf = 1; /* allow dtmf */
2256 // if (call_countrelations(ea_endpoint->ep_call_id) == 2)
2259 /* other calls with no caller id (or not available for the extension) and force colp */
2260 if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE)
2262 e_connectinfo.present = INFO_PRESENT_NOTAVAIL;
2263 if (portlist->port_type==PORT_TYPE_DSS1_TE_OUT || portlist->port_type==PORT_TYPE_DSS1_NT_OUT) /* external extension answered */
2265 port = find_port_id(portlist->port_id);
2268 SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.number, &e_connectinfo.ntype));
2269 e_connectinfo.present = INFO_PRESENT_ALLOWED;
2273 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
2274 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
2275 message_put(message);
2277 if (ea_endpoint->ep_call_id)
2279 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2280 message->param.channel = CHANNEL_STATE_CONNECT;
2281 message_put(message);
2282 } else if (!e_adminid)
2285 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have a callback, so we create a call with cbcaller: \"%s\".\n", ea_endpoint->ep_serial, e_cbcaller);
2286 SCPY(e_ext.number, e_cbcaller);
2287 new_state(EPOINT_STATE_IN_OVERLAP);
2288 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) callback from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2290 /* get extension's info about terminal */
2291 if (!read_extension(&e_ext, e_ext.number))
2293 /* extension doesn't exist */
2294 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2295 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
2296 new_state(EPOINT_STATE_OUT_DISCONNECT);
2297 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
2301 /* put prefix in front of e_cbdialing */
2302 SPRINT(buffer, "%s%s", e_ext.prefix, e_cbdialing);
2303 SCPY(e_dialinginfo.number, buffer);
2304 e_dialinginfo.itype = INFO_ITYPE_EXTERN;
2305 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
2307 /* use caller id (or if exist: id_next_call) for this call */
2308 e_callerinfo.screen = INFO_SCREEN_NETWORK;
2309 SCPY(e_callerinfo.intern, e_ext.number);
2310 if (e_ext.id_next_call_present >= 0)
2312 SCPY(e_callerinfo.id, e_ext.id_next_call);
2313 e_callerinfo.present = e_ext.id_next_call_present;
2314 e_callerinfo.ntype = e_ext.id_next_call_type;
2315 e_ext.id_next_call_present = -1;
2316 /* extension is written */
2317 write_extension(&e_ext, e_ext.number);
2320 SCPY(e_callerinfo.id, e_ext.callerid);
2321 e_callerinfo.present = e_ext.callerid_present;
2322 e_callerinfo.ntype = e_ext.callerid_type;
2325 e_connectedmode = 1; /* dtmf-hangup & disconnect prevention */
2328 /* check if caller id is NOT authenticated */
2329 if (!parse_callbackauth(e_ext.number, &e_callbackinfo))
2331 /* make call state to enter password */
2332 new_state(EPOINT_STATE_IN_OVERLAP);
2333 e_action = &action_password_write;
2334 e_match_timeout = 0;
2335 e_match_to_action = NULL;
2336 e_dialinginfo.number[0] = '\0';
2337 e_extdialing = strchr(e_dialinginfo.number, '\0');
2338 e_password_timeout = now+20;
2342 /* incoming call (callback) */
2343 e_ruleset = ruleset_main;
2345 e_rule = e_ruleset->rule_first;
2347 e_extdialing = e_dialinginfo.number;
2348 if (e_dialinginfo.number[0])
2350 set_tone(portlist, "dialing");
2354 set_tone(portlist, "dialpbx");
2357 } else /* testcall */
2359 set_tone(portlist, "hold");
2362 /* start recording if enabled, not when answering machine answers */
2363 if (param->connectinfo.itype!=INFO_ITYPE_VBOX && e_ext.number[0] && e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO))
2365 /* check if we are a terminal */
2366 if (e_ext.number[0] == '\0')
2367 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
2370 port = find_port_id(portlist->port_id);
2372 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
2377 /* port MESSAGE_DISCONNECT MESSAGE_RELEASE */
2378 void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
2380 struct message *message;
2382 unsigned long port_id = portlist->port_id;
2386 /* signal to call tool */
2387 admin_call_response(e_adminid, (message_type==MESSAGE_DISCONNECT)?ADMIN_CALL_DISCONNECT:ADMIN_CALL_RELEASE, "", param->disconnectinfo.cause, param->disconnectinfo.location, 0);
2389 trace_header((message_type==MESSAGE_DISCONNECT)?"DISCONNECT":"RELEASE", DIRECTION_IN);
2390 add_trace("cause", "value", "%d", param->disconnectinfo.cause);
2391 add_trace("cause", "location", "%d", param->disconnectinfo.location);
2394 //#warning does this work? only disconnect when incoming port hat not already disconnected yet?
2395 if (e_state==EPOINT_STATE_IN_DISCONNECT && message_type!=MESSAGE_RELEASE)// || e_state==EPOINT_STATE_OUT_DISCONNECT || e_state==EPOINT_STATE_IDLE)
2397 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are already disconnected.\n", ea_endpoint->ep_serial);
2402 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);
2403 if (param->disconnectinfo.cause == CAUSE_REJECTED) /* call rejected */
2405 e_multipoint_cause = CAUSE_REJECTED;
2406 e_multipoint_location = param->disconnectinfo.location;
2408 if (param->disconnectinfo.cause==CAUSE_NORMAL && e_multipoint_cause!=CAUSE_REJECTED) /* reject via hangup */
2410 e_multipoint_cause = CAUSE_NORMAL;
2411 e_multipoint_location = param->disconnectinfo.location;
2413 if (param->disconnectinfo.cause==CAUSE_BUSY && e_multipoint_cause!=CAUSE_REJECTED && e_multipoint_cause!=CAUSE_NORMAL) /* busy */
2415 e_multipoint_cause = CAUSE_BUSY;
2416 e_multipoint_location = param->disconnectinfo.location;
2418 if (param->disconnectinfo.cause==CAUSE_OUTOFORDER && e_multipoint_cause!=CAUSE_BUSY && e_multipoint_cause!=CAUSE_REJECTED && e_multipoint_cause!=CAUSE_NORMAL) /* no L1 */
2420 e_multipoint_cause = CAUSE_OUTOFORDER;
2421 e_multipoint_location = param->disconnectinfo.location;
2423 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 */
2425 e_multipoint_cause = param->disconnectinfo.cause;
2426 e_multipoint_location = param->disconnectinfo.location;
2428 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new multipoint cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location);
2430 /* check if we have more than one portlist relation and we just ignore the disconnect */
2431 if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist->next)
2433 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the disconnect was from a multipoint call. we just release that relation.\n", ea_endpoint->ep_serial);
2434 portlist = ea_endpoint->ep_portlist;
2437 if (portlist->port_id == port_id)
2439 portlist = portlist->next;
2443 PERROR("EPOINT(%d) software error: no portlist related to the calling port.\n", ea_endpoint->ep_serial);
2446 if (message_type != MESSAGE_RELEASE)
2448 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2449 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2450 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2451 message_put(message);
2452 logmessage(message);
2454 ea_endpoint->free_portlist(portlist);
2455 return; /* one relation removed */
2457 if (e_multipoint_cause)
2459 cause = e_multipoint_cause;
2460 location = e_multipoint_location;
2463 cause = param->disconnectinfo.cause;
2464 location = param->disconnectinfo.location;
2467 e_cfnr_call = e_cfnr_release = 0;
2469 /* process hangup */
2470 process_hangup(e_call_cause, e_call_location);
2471 e_multipoint_cause = 0;
2472 e_multipoint_location = LOCATION_PRIVATE_LOCAL;
2474 /* tone to disconnected end */
2475 SPRINT(buffer, "cause_%02x", cause);
2476 if (ea_endpoint->ep_portlist)
2477 set_tone(ea_endpoint->ep_portlist, buffer);
2479 new_state(EPOINT_STATE_IN_DISCONNECT);
2480 if (ea_endpoint->ep_call_id)
2482 int haspatterns = 0;
2483 /* check if pattern is available */
2484 if (ea_endpoint->ep_portlist)
2485 if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->earlyb)
2486 #warning wie ist das bei einem asterisk, gibts auch tones?
2487 if (callpbx_countrelations(ea_endpoint->ep_call_id)==2 // we must count relations, in order not to disturb the conference ; NOTE:
2488 && message_type != MESSAGE_RELEASE) // if we release, we are done
2492 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has patterns.\n", ea_endpoint->ep_serial);
2493 /* indicate patterns */
2494 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_PATTERN);
2495 message_put(message);
2496 /* connect audio, if not already */
2497 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2498 message->param.channel = CHANNEL_STATE_CONNECT;
2499 message_put(message);
2500 /* send disconnect */
2501 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
2502 memcpy(&message->param, param, sizeof(union parameter));
2503 message_put(message);
2504 /* disable encryption if disconnected */
2505 //PERROR("REMOVE ME: state =%d, %d\n", e_crypt_state, e_crypt);
2507 cryptman_message(CI_DISCONNECT_IND, NULL, 0);
2511 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
2514 release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, callcause, portcause */
2515 return; /* must exit here */
2518 /* port MESSAGE_TIMEOUT */
2519 void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type, union parameter *param)
2523 trace_header("TIMEOUT", DIRECTION_IN);
2524 message_type = MESSAGE_DISCONNECT;
2525 switch (param->state)
2527 case PORT_STATE_OUT_SETUP:
2528 case PORT_STATE_OUT_OVERLAP:
2529 add_trace("state", NULL, "outgoing setup/dialing");
2531 /* no user responding */
2532 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2533 return; /* must exit here */
2535 case PORT_STATE_IN_SETUP:
2536 case PORT_STATE_IN_OVERLAP:
2537 add_trace("state", NULL, "incoming setup/dialing");
2538 param->disconnectinfo.cause = CAUSE_INVALID; /* number incomplete */
2539 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2542 case PORT_STATE_OUT_PROCEEDING:
2543 add_trace("state", NULL, "outgoing proceeding");
2545 param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
2546 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2547 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2548 return; /* must exit here */
2550 case PORT_STATE_IN_PROCEEDING:
2551 add_trace("state", NULL, "incoming proceeding");
2552 param->disconnectinfo.cause = CAUSE_NOUSER;
2553 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL; /* no user responding */
2556 case PORT_STATE_OUT_ALERTING:
2557 add_trace("state", NULL, "outgoing alerting");
2559 param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
2560 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2561 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2562 return; /* must exit here */
2564 case PORT_STATE_IN_ALERTING:
2565 add_trace("state", NULL, "incoming alerting");
2566 param->disconnectinfo.cause = CAUSE_NOANSWER;
2567 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2570 case PORT_STATE_IN_DISCONNECT:
2571 case PORT_STATE_OUT_DISCONNECT:
2572 add_trace("state", NULL, "disconnect");
2574 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
2575 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2576 return; /* must exit here */
2579 param->disconnectinfo.cause = 31; /* normal unspecified */
2580 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2583 /* release call, disconnect isdn */
2585 new_state(EPOINT_STATE_OUT_DISCONNECT);
2586 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2587 SCPY(e_tone, cause);
2590 set_tone(portlist, cause);
2591 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2592 portlist = portlist->next;
2594 release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
2597 /* port MESSAGE_NOTIFY */
2598 void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, union parameter *param)
2600 struct message *message;
2604 /* signal to call tool */
2605 admin_call_response(e_adminid, ADMIN_CALL_NOTIFY, numberrize_callerinfo(param->notifyinfo.id,param->notifyinfo.ntype), 0, 0, param->notifyinfo.notify);
2606 if (param->notifyinfo.notify)
2608 e_rx_state = track_notify(e_rx_state, param->notifyinfo.notify);
2611 /* if we get notification from stack, local shows if we disabled/enabled audio stream */
2612 if (param->notifyinfo.local) switch(param->notifyinfo.notify)
2614 case INFO_NOTIFY_REMOTE_HOLD:
2615 case INFO_NOTIFY_USER_SUSPENDED:
2616 /* tell call about it */
2617 if (ea_endpoint->ep_call_id)
2619 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2620 message->param.channel = CHANNEL_STATE_HOLD;
2621 message_put(message);
2625 case INFO_NOTIFY_REMOTE_RETRIEVAL:
2626 case INFO_NOTIFY_USER_RESUMED:
2627 /* set volume of rx and tx */
2628 if (param->setup.callerinfo.itype == INFO_ITYPE_INTERN)
2629 if (e_ext.txvol!=256 || e_ext.rxvol!=256)
2632 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2633 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2634 message->param.mISDNsignal.rxvol = e_ext.txvol;
2635 message->param.mISDNsignal.txvol = e_ext.rxvol;
2636 message_put(message);
2638 /* set current tone */
2640 set_tone(portlist, e_tone);
2641 /* tell call about it */
2642 if (ea_endpoint->ep_call_id)
2644 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
2645 message->param.channel = CHANNEL_STATE_CONNECT;
2646 message_put(message);
2651 /* get name of notify */
2652 switch(param->notifyinfo.notify)
2658 logtext = "USER_SUSPENDED";
2661 logtext = "BEARER_SERVICE_CHANGED";
2664 logtext = "USER_RESUMED";
2667 logtext = "CONFERENCE_ESTABLISHED";
2670 logtext = "CONFERENCE_DISCONNECTED";
2673 logtext = "OTHER_PARTY_ADDED";
2676 logtext = "ISOLATED";
2679 logtext = "REATTACHED";
2682 logtext = "OTHER_PARTY_ISOLATED";
2685 logtext = "OTHER_PARTY_REATTACHED";
2688 logtext = "OTHER_PARTY_SPLIT";
2691 logtext = "OTHER_PARTY_DISCONNECTED";
2694 logtext = "CONFERENCE_FLOATING";
2697 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
2700 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
2703 logtext = "CALL_IS_A_WAITING_CALL";
2706 logtext = "DIVERSION_ACTIVATED";
2709 logtext = "RESERVED_CT_1";
2712 logtext = "RESERVED_CT_2";
2715 logtext = "REVERSE_CHARGING";
2718 logtext = "REMOTE_HOLD";
2721 logtext = "REMOTE_RETRIEVAL";
2724 logtext = "CALL_IS_DIVERTING";
2727 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
2731 trace_header("NOTIFY", DIRECTION_IN);
2732 if (param->notifyinfo.notify)
2733 add_trace("indicator", NULL, "%s", logtext);
2734 if (param->notifyinfo.id)
2736 add_trace("redir'on", "number", "%s", numberrize_callerinfo(param->notifyinfo.id, param->notifyinfo.ntype));
2737 if (param->notifyinfo.present == INFO_PRESENT_RESTRICTED)
2738 add_trace("redir'on", "present", "restricted");
2740 if (param->notifyinfo.display[0])
2741 add_trace("display", NULL, "%s", param->notifyinfo.display);
2744 /* notify call if available */
2745 if (ea_endpoint->ep_call_id)
2747 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_NOTIFY);
2748 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
2749 message_put(message);
2754 /* port MESSAGE_FACILITY */
2755 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
2757 struct message *message;
2759 trace_header("FACILITY", DIRECTION_IN);
2762 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_FACILITY);
2763 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2764 message_put(message);
2767 /* port MESSAGE_SUSPEND */
2768 /* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
2769 void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
2771 trace_header("SUSPEND", DIRECTION_IN);
2773 /* epoint is now parked */
2774 ea_endpoint->ep_park = 1;
2775 memcpy(ea_endpoint->ep_park_callid, param->parkinfo.callid, sizeof(ea_endpoint->ep_park_callid));
2776 ea_endpoint->ep_park_len = (param->parkinfo.len>8)?8:param->parkinfo.len;
2778 /* remove port relation */
2779 ea_endpoint->free_portlist(portlist);
2782 /* port MESSAGE_RESUME */
2783 /* NOTE: before resume, the active-notification must be done in order to set call mixer */
2784 void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
2786 trace_header("RESUME", DIRECTION_IN);
2788 /* epoint is now resumed */
2789 ea_endpoint->ep_park = 0;
2794 /* port sends message to the endpoint
2796 void EndpointAppPBX::ea_message_port(unsigned long port_id, int message_type, union parameter *param)
2798 struct port_list *portlist;
2799 struct message *message;
2802 portlist = ea_endpoint->ep_portlist;
2805 if (port_id == portlist->port_id)
2807 portlist = portlist->next;
2811 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);
2815 // PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
2816 switch(message_type)
2818 case MESSAGE_DATA: /* data from port */
2819 /* send back to source for recording */
2822 message = message_create(ea_endpoint->ep_serial, port_id, EPOINT_TO_PORT, message_type);
2823 memcpy(&message->param, param, sizeof(union parameter));
2824 message_put(message);
2827 /* check if there is a call */
2828 if (!ea_endpoint->ep_call_id)
2830 /* continue if only one portlist */
2831 if (ea_endpoint->ep_portlist->next != NULL)
2833 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
2834 memcpy(&message->param, param, sizeof(union parameter));
2835 message_put(message);
2838 case MESSAGE_TONE_EOF: /* tone is end of file */
2839 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
2842 if (e_action->index == ACTION_VBOX_PLAY)
2846 if (e_action->index == ACTION_EFI)
2853 case MESSAGE_TONE_COUNTER: /* counter info received */
2854 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);
2856 if (e_action->index == ACTION_VBOX_PLAY)
2858 e_vbox_counter = param->counter.current;
2859 if (param->counter.max >= 0)
2860 e_vbox_counter_max = param->counter.max;
2864 /* PORT sends SETUP message */
2866 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);
2867 if (e_state!=EPOINT_STATE_IDLE)
2869 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
2872 port_setup(portlist, message_type, param);
2875 /* PORT sends INFORMATION message */
2876 case MESSAGE_INFORMATION: /* additional digits received */
2877 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call dialing more=%s (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, param->information.number, e_ext.number, e_callerinfo.id);
2878 port_information(portlist, message_type, param);
2881 /* PORT sends FACILITY message */
2882 case MESSAGE_FACILITY:
2883 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2884 port_facility(portlist, message_type, param);
2887 /* PORT sends DTMF message */
2888 case MESSAGE_DTMF: /* dtmf digits received */
2889 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf digit=%c (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, param->dtmf, e_ext.number, e_callerinfo.id);
2890 port_dtmf(portlist, message_type, param);
2893 /* PORT sends CRYPT message */
2894 case MESSAGE_CRYPT: /* crypt response received */
2895 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) crypt response=%d\n", ea_endpoint->ep_serial, param->crypt.type);
2896 port_crypt(portlist, message_type, param);
2899 /* PORT sends MORE message */
2900 case MESSAGE_OVERLAP:
2901 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) outgoing call is accepted [overlap dialing] (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2902 if (e_state != EPOINT_STATE_OUT_SETUP)
2904 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);
2907 port_overlap(portlist, message_type, param);
2910 /* PORT sends PROCEEDING message */
2911 case MESSAGE_PROCEEDING: /* port is proceeding */
2912 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) outgoing call is proceeding (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2913 if (e_state!=EPOINT_STATE_OUT_SETUP
2914 && e_state!=EPOINT_STATE_OUT_OVERLAP)
2916 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);
2919 port_proceeding(portlist, message_type, param);
2922 /* PORT sends ALERTING message */
2923 case MESSAGE_ALERTING:
2924 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) outgoing call is ringing (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2925 if (e_state!=EPOINT_STATE_OUT_SETUP
2926 && e_state!=EPOINT_STATE_OUT_OVERLAP
2927 && e_state!=EPOINT_STATE_OUT_PROCEEDING)
2929 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);
2932 port_alerting(portlist, message_type, param);
2935 /* PORT sends CONNECT message */
2936 case MESSAGE_CONNECT:
2937 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) outgoing call connected to %s (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_connectinfo.id, e_ext.number, e_callerinfo.id);
2938 if (e_state!=EPOINT_STATE_OUT_SETUP
2939 && e_state!=EPOINT_STATE_OUT_OVERLAP
2940 && e_state!=EPOINT_STATE_OUT_PROCEEDING
2941 && e_state!=EPOINT_STATE_OUT_ALERTING)
2943 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
2946 port_connect(portlist, message_type, param);
2949 /* PORT sends DISCONNECT message */
2950 case MESSAGE_DISCONNECT: /* port is disconnected */
2951 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call disconnect with cause=%d location=%d (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, param->disconnectinfo.cause, param->disconnectinfo.location, e_ext.number, e_callerinfo.id);
2952 port_disconnect_release(portlist, message_type, param);
2955 /* PORT sends a RELEASE message */
2956 case MESSAGE_RELEASE: /* port releases */
2957 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) release with cause=%d location=%d (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, param->disconnectinfo.cause, param->disconnectinfo.location, e_ext.number, e_callerinfo.id);
2958 /* portlist is release at port_disconnect_release, thanx Paul */
2959 port_disconnect_release(portlist, message_type, param);
2962 /* PORT sends a TIMEOUT message */
2963 case MESSAGE_TIMEOUT:
2964 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received timeout (state=%d).\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->state);
2965 port_timeout(portlist, message_type, param);
2966 break; /* release */
2968 /* PORT sends a NOTIFY message */
2969 case MESSAGE_NOTIFY:
2970 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received notify.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2971 port_notify(portlist, message_type, param);
2974 /* PORT sends a SUSPEND message */
2975 case MESSAGE_SUSPEND:
2976 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received suspend.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2977 port_suspend(portlist, message_type, param);
2978 break; /* suspend */
2980 /* PORT sends a RESUME message */
2981 case MESSAGE_RESUME:
2982 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received resume.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2983 port_resume(portlist, message_type, param);
2987 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received a wrong message: %d\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, message);
2990 /* Note: this endpoint may be destroyed, so we MUST return */
2994 /* messages from port
2996 /* call MESSAGE_CRYPT */
2997 void EndpointAppPBX::call_crypt(struct port_list *portlist, int message_type, union parameter *param)
2999 switch(param->crypt.type)
3001 /* message from remote port to "crypt manager" */
3002 case CU_ACTK_REQ: /* activate key-exchange */
3003 case CU_ACTS_REQ: /* activate shared key */
3004 case CU_DACT_REQ: /* deactivate */
3005 case CU_INFO_REQ: /* request last info message */
3006 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
3009 /* message from "crypt manager" to user */
3010 case CU_ACTK_CONF: /* key-echange done */
3011 case CU_ACTS_CONF: /* shared key done */
3012 case CU_DACT_CONF: /* deactivated */
3013 case CU_DACT_IND: /* deactivated */
3014 case CU_ERROR_IND: /* receive error message */
3015 case CU_INFO_IND: /* receive info message */
3016 case CU_INFO_CONF: /* receive info message */
3017 encrypt_result(param->crypt.type, (char *)param->crypt.data);
3021 PERROR("EPOINT(%d) epoint with terminal '%s' (caller id '%s') unknown crypt message: '%d'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->crypt.type);
3025 /* call MESSAGE_INFORMATION */
3026 void EndpointAppPBX::call_information(struct port_list *portlist, int message_type, union parameter *param)
3028 struct message *message;
3034 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
3035 memcpy(&message->param.information, ¶m->information, sizeof(struct dialing_info));
3036 message_put(message);
3037 logmessage(message);
3038 portlist = portlist->next;
3042 /* call MESSAGE_FACILITY */
3043 void EndpointAppPBX::call_facility(struct port_list *portlist, int message_type, union parameter *param)
3045 struct message *message;
3047 if (!e_ext.facility)
3054 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_FACILITY);
3055 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
3056 message_put(message);
3057 logmessage(message);
3058 portlist = portlist->next;
3062 /* call MESSAGE_MORE */
3063 void EndpointAppPBX::call_overlap(struct port_list *portlist, int message_type, union parameter *param)
3065 struct message *message;
3067 new_state(EPOINT_STATE_IN_OVERLAP);
3070 if (e_call_pattern && e_ext.own_setup)
3072 /* disconnect audio */
3073 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3074 message->param.channel = CHANNEL_STATE_HOLD;
3075 message_put(message);
3077 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
3079 set_tone(portlist, "dialtone");
3082 if (e_ext.number[0])
3083 set_tone(portlist, "dialpbx");
3085 set_tone(portlist, "dialtone");
3088 /* call MESSAGE_PROCEEDING */
3089 void EndpointAppPBX::call_proceeding(struct port_list *portlist, int message_type, union parameter *param)
3091 struct message *message;
3093 new_state(EPOINT_STATE_IN_PROCEEDING);
3095 /* own proceeding tone */
3098 /* connect / disconnect audio */
3099 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3100 if (e_ext.own_proceeding)
3101 message->param.channel = CHANNEL_STATE_HOLD;
3103 message->param.channel = CHANNEL_STATE_CONNECT;
3104 message_put(message);
3106 // UCPY(e_call_tone, "proceeding");
3109 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3110 message_put(message);
3111 logmessage(message);
3113 set_tone(portlist, "proceeding");
3116 /* call MESSAGE_ALERTING */
3117 void EndpointAppPBX::call_alerting(struct port_list *portlist, int message_type, union parameter *param)
3119 struct message *message;
3121 new_state(EPOINT_STATE_IN_ALERTING);
3123 /* own alerting tone */
3126 /* connect / disconnect audio */
3127 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3128 if (e_ext.own_alerting)
3129 message->param.channel = CHANNEL_STATE_HOLD;
3131 message->param.channel = CHANNEL_STATE_CONNECT;
3132 message_put(message);
3136 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
3137 message_put(message);
3138 logmessage(message);
3140 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
3142 set_tone(portlist, "ringing");
3145 if (e_ext.number[0])
3146 set_tone(portlist, "ringpbx");
3148 set_tone(portlist, "ringing");
3151 /* call MESSAGE_CONNECT */
3152 void EndpointAppPBX::call_connect(struct port_list *portlist, int message_type, union parameter *param)
3154 struct message *message;
3156 new_state(EPOINT_STATE_CONNECT);
3157 // UCPY(e_call_tone, "");
3158 if (e_ext.number[0])
3159 e_dtmf = 1; /* allow dtmf */
3161 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_callerinfo));
3164 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3165 memcpy(&message->param, param, sizeof(union parameter));
3166 /* screen by interface */
3167 if (e_connectinfo.interface[0])
3169 /* screen incoming caller id */
3170 screen(1, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present);
3172 memcpy(&message->param.connnectinfo, e_connectinfo);
3174 /* screen clip if prefix is required */
3175 if (e_ext.number[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0])
3177 SCPY(message->param.connectinfo.id, e_ext.clip_prefix);
3178 SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype));
3179 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
3182 /* use internal caller id */
3183 if (e_ext.number[0] && e_connectinfo.intern[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
3185 SCPY(message->param.connectinfo.id, e_connectinfo.intern);
3186 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
3189 /* handle restricted caller ids */
3190 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);
3191 /* display callerid if desired for extension */
3192 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));
3194 /* use conp, if enabld */
3196 message->param.connectinfo.name[0] = '\0';
3199 message_put(message);
3200 logmessage(message);
3202 set_tone(portlist, NULL);
3204 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3205 message->param.channel = CHANNEL_STATE_CONNECT;
3206 message_put(message);
3210 /* call MESSAGE_DISCONNECT MESSAGE_RELEASE */
3211 void EndpointAppPBX::call_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
3214 struct message *message;
3217 /* be sure that we are active */
3219 e_tx_state = NOTIFY_STATE_ACTIVE;
3221 /* we are powerdialing, if e_powerdialing is set and limit is not exceeded if given */
3222 if (e_powerdialing && ((e_powercount+1)<e_powerlimit || e_powerlimit<1))
3224 release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
3226 /* set time for power dialing */
3227 e_powerdialing = now_d + e_powerdelay; /* set redial in the future */
3230 /* set redial tone */
3231 if (ea_endpoint->ep_portlist)
3235 set_tone(ea_endpoint->ep_portlist, "redial");
3236 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') redialing in %d seconds\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, (int)e_powerdelay);
3237 /* send proceeding when powerdialing and still setup (avoid dialing timeout) */
3238 if (e_state==EPOINT_STATE_IN_OVERLAP)
3240 new_state(EPOINT_STATE_IN_PROCEEDING);
3243 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3244 message_put(message);
3245 logmessage(message);
3247 /* caused the error, that the first knock sound was not there */
3248 /* set_tone(portlist, "proceeding"); */
3250 /* send display of powerdialing */
3251 if (e_ext.display_dialing)
3255 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3257 SPRINT(message->param.notifyinfo.display, "Retry %d of %d", e_powercount, e_powerlimit);
3259 SPRINT(message->param.notifyinfo.display, "Retry %d", e_powercount);
3260 message_put(message);
3261 logmessage(message);
3262 portlist = portlist->next;
3271 if ((e_state!=EPOINT_STATE_CONNECT
3272 && e_state!=EPOINT_STATE_OUT_DISCONNECT
3273 && e_state!=EPOINT_STATE_IN_OVERLAP
3274 && e_state!=EPOINT_STATE_IN_PROCEEDING
3275 && e_state!=EPOINT_STATE_IN_ALERTING)
3276 || !ea_endpoint->ep_portlist) /* or no port */
3278 process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
3279 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause); /* RELEASE_TYPE, call, port */
3280 return; /* must exit here */
3285 e_call_cause = param->disconnectinfo.cause;
3286 e_call_location = param->disconnectinfo.location;
3289 /* on release we need the audio again! */
3290 if (message_type == MESSAGE_RELEASE)
3293 ea_endpoint->ep_call_id = 0;
3295 /* disconnect and select tone */
3296 new_state(EPOINT_STATE_OUT_DISCONNECT);
3297 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
3298 /* if own_cause, we must release the call */
3299 if (e_ext.own_cause /* own cause */
3300 || !e_call_pattern) /* no patterns */
3302 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);
3303 if (message_type != MESSAGE_RELEASE)
3304 release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
3306 } else /* else we enable audio */
3308 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3309 message->param.channel = CHANNEL_STATE_CONNECT;
3310 message_put(message);
3312 /* send disconnect message */
3313 SCPY(e_tone, cause);
3316 set_tone(portlist, cause);
3317 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
3318 portlist = portlist->next;
3322 /* call MESSAGE_SETUP */
3323 void EndpointAppPBX::call_setup(struct port_list *portlist, int message_type, union parameter *param)
3325 struct message *message;
3327 /* if we already in setup state, we just update the dialing with new digits */
3328 if (e_state == EPOINT_STATE_OUT_SETUP
3329 || e_state == EPOINT_STATE_OUT_OVERLAP)
3331 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we are in setup state, so we do overlap dialing.\n", ea_endpoint->ep_serial);
3332 /* if digits changed, what we have already dialed */
3333 if (!!strncmp(e_dialinginfo.number,param->setup.dialinginfo.number,strlen(e_dialinginfo.number)))
3335 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);
3336 /* release all ports */
3337 while((portlist = ea_endpoint->ep_portlist))
3339 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
3340 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
3341 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3342 message_put(message);
3343 logmessage(message);
3344 ea_endpoint->free_portlist(portlist);
3347 /* disconnect audio */
3348 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3349 message->param.channel = CHANNEL_STATE_HOLD;
3350 message_put(message);
3352 /* get dialing info */
3353 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3354 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3355 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3356 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3357 new_state(EPOINT_STATE_OUT_OVERLAP);
3360 e_redial = now_d + 1; /* set redial one second in the future */
3363 /* if we have a pending redial, so we just adjust the dialing number */
3366 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);
3367 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3370 if (!ea_endpoint->ep_portlist)
3372 PERROR("ERROR: overlap dialing to a NULL port relation\n");
3374 if (ea_endpoint->ep_portlist->next)
3376 PERROR("ERROR: overlap dialing to a port_list port relation\n");
3378 if (e_state == EPOINT_STATE_OUT_SETUP)
3381 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);
3382 SCAT(e_dialing_queue, param->setup.dialinginfo.number + strlen(e_dialinginfo.number));
3386 /* get what we have not dialed yet */
3387 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));
3388 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
3389 SCPY(message->param.information.number, param->setup.dialinginfo.number + strlen(e_dialinginfo.number));
3390 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
3391 message_put(message);
3392 logmessage(message);
3394 /* always store what we have dialed or queued */
3395 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3399 if (e_state != EPOINT_STATE_IDLE)
3401 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
3404 /* if an internal extension is dialed, copy that number */
3405 if (param->setup.dialinginfo.itype==INFO_ITYPE_INTERN || param->setup.dialinginfo.itype==INFO_ITYPE_VBOX)
3406 SCPY(e_ext.number, param->setup.dialinginfo.number);
3407 /* if an internal extension is dialed, get extension's info about caller */
3408 if (e_ext.number[0])
3410 if (!read_extension(&e_ext, e_ext.number))
3412 e_ext.number[0] = '\0';
3413 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the called terminal='%s' is not found in directory tree!\n", ea_endpoint->ep_serial, e_ext.number);
3417 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3418 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3419 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3420 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3422 /* screen by interface */
3423 if (e_callerinfo.interface[0])
3425 /* screen incoming caller id */
3426 screen(1, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present);
3429 /* process (voice over) data calls */
3430 if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO)
3432 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) handling data call as audio call: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
3433 memset(&e_capainfo, 0, sizeof(e_capainfo));
3434 e_capainfo.bearer_capa = INFO_BC_AUDIO;
3435 e_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
3436 e_capainfo.bearer_info1 = (options.law=='u')?INFO_INFO1_ULAW:INFO_INFO1_ALAW;
3439 new_state(EPOINT_STATE_OUT_SETUP);
3440 /* call special setup routine */
3444 /* call MESSAGE_mISDNSIGNAL */
3445 void EndpointAppPBX::call_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param)
3447 struct message *message;
3451 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
3452 memcpy(&message->param, param, sizeof(union parameter));
3453 message_put(message);
3454 portlist = portlist->next;
3458 /* call MESSAGE_NOTIFY */
3459 void EndpointAppPBX::call_notify(struct port_list *portlist, int message_type, union parameter *param)
3461 struct message *message;
3464 if (param->notifyinfo.notify)
3466 new_state = track_notify(e_tx_state, param->notifyinfo.notify);
3467 // /* if notification was generated locally, we turn hold music on/off */
3468 // if (param->notifyinfo.local)
3469 // 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)
3474 if (new_state!=NOTIFY_STATE_HOLD && new_state!=NOTIFY_STATE_SUSPEND)
3478 set_tone(portlist, "");
3479 portlist = portlist->next;
3481 portlist = ea_endpoint->ep_portlist;
3486 if (new_state==NOTIFY_STATE_HOLD || new_state==NOTIFY_STATE_SUSPEND)
3490 set_tone(portlist, "hold");
3491 portlist = portlist->next;
3493 portlist = ea_endpoint->ep_portlist;
3498 /* save new state */
3499 e_tx_state = new_state;
3502 /* notify port(s) about it */
3505 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3506 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
3507 /* handle restricted caller ids */
3508 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);
3509 /* display callerid if desired for extension */
3510 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));
3511 message_put(message);
3512 logmessage(message);
3513 portlist = portlist->next;
3517 /* call sends messages to the endpoint
3519 void EndpointAppPBX::ea_message_call(unsigned long call_id, int message_type, union parameter *param)
3521 struct port_list *portlist;
3522 struct message *message;
3526 PERROR("EPOINT(%d) error: call == NULL.\n", ea_endpoint->ep_serial);
3530 portlist = ea_endpoint->ep_portlist;
3532 /* send MESSAGE_DATA to port */
3533 if (call_id == ea_endpoint->ep_call_id)
3535 if (message_type == MESSAGE_DATA)
3537 /* skip if no port relation */
3540 /* skip if more than one port relation */
3543 /* send audio data to port */
3544 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DATA);
3545 memcpy(&message->param, param, sizeof(union parameter));
3546 message_put(message);
3551 // PDEBUG(DEBUG_EPOINT, "EPOINT(%d) received message %d for active call (terminal %s, caller id %s state=%d)\n", ea_endpoint->ep_serial, message, e_ext.number, e_callerinfo.id, e_state);
3552 switch(message_type)
3554 /* CALL SENDS CRYPT message */
3556 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received crypt message: '%d'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->crypt.type);
3557 call_crypt(portlist, message_type, param);
3560 /* CALL sends INFORMATION message */
3561 case MESSAGE_INFORMATION:
3562 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received more digits: '%s'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->information.number);
3563 call_information(portlist, message_type, param);
3566 /* CALL sends FACILITY message */
3567 case MESSAGE_FACILITY:
3568 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received facility\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3569 call_facility(portlist, message_type, param);
3572 /* CALL sends OVERLAP message */
3573 case MESSAGE_OVERLAP:
3574 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received 'more info available'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3575 if (e_state!=EPOINT_STATE_IN_SETUP
3576 && e_state!=EPOINT_STATE_IN_OVERLAP)
3578 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3581 call_overlap(portlist, message_type, param);
3584 /* CALL sends PROCEEDING message */
3585 case MESSAGE_PROCEEDING:
3586 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s (caller id '%s') received proceeding\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3587 if(e_state!=EPOINT_STATE_IN_OVERLAP)
3589 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3592 call_proceeding(portlist, message_type, param);
3595 /* CALL sends ALERTING message */
3596 case MESSAGE_ALERTING:
3597 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received alerting\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3598 if (e_state!=EPOINT_STATE_IN_OVERLAP
3599 && e_state!=EPOINT_STATE_IN_PROCEEDING)
3601 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state.\n", ea_endpoint->ep_serial);
3604 call_alerting(portlist, message_type, param);
3607 /* CALL sends CONNECT message */
3608 case MESSAGE_CONNECT:
3609 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received connect\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3610 if (e_state!=EPOINT_STATE_IN_OVERLAP
3611 && e_state!=EPOINT_STATE_IN_PROCEEDING
3612 && e_state!=EPOINT_STATE_IN_ALERTING)
3614 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
3617 call_connect(portlist, message_type, param);
3620 /* CALL sends DISCONNECT/RELEASE message */
3621 case MESSAGE_DISCONNECT: /* call disconnect */
3622 case MESSAGE_RELEASE: /* call releases */
3623 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received %s with cause %d location %d\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, (message_type==MESSAGE_DISCONNECT)?"disconnect":"release", param->disconnectinfo.cause, param->disconnectinfo.location);
3624 call_disconnect_release(portlist, message_type, param);
3627 /* CALL sends SETUP message */
3629 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);
3630 call_setup(portlist, message_type, param);
3634 /* CALL sends special mISDNSIGNAL message */
3635 case MESSAGE_mISDNSIGNAL: /* isdn message to port */
3636 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received mISDNsignal message.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3637 call_mISDNsignal(portlist, message_type, param);
3640 /* CALL has pattern available */
3641 case MESSAGE_PATTERN: /* indicating pattern available */
3642 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received pattern availability.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3643 if (!e_call_pattern)
3645 PDEBUG(DEBUG_EPOINT, "-> pattern becomes available\n");
3650 set_tone(portlist, NULL);
3651 portlist = portlist->next;
3653 /* connect our audio tx and rx (blueboxing should be possibe before connect :)*/
3654 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3655 message->param.channel = CHANNEL_STATE_CONNECT;
3656 message_put(message);
3657 // /* tell remote epoint to connect audio also, because we like to hear the patterns */
3658 // message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_REMOTE_AUDIO);
3659 // message->param.channel = CHANNEL_STATE_CONNECT;
3660 // message_put(message);
3661 // patterns are available, remote already connected audio
3665 /* CALL has no pattern available */
3666 case MESSAGE_NOPATTERN: /* indicating no pattern available */
3667 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received pattern NOT available.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3670 PDEBUG(DEBUG_EPOINT, "-> pattern becomes unavailable\n");
3672 /* disconnect our audio tx and rx */
3673 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3674 message->param.channel = CHANNEL_STATE_HOLD;
3675 message_put(message);
3680 /* CALL (dunno at the moment) */
3681 case MESSAGE_REMOTE_AUDIO:
3682 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received audio remote request.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3683 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3684 message->param.channel = param->channel;
3685 message_put(message);
3689 /* CALL sends a notify message */
3690 case MESSAGE_NOTIFY:
3691 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received notify.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3692 call_notify(portlist, message_type, param);
3696 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received a wrong message: #%d\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, message);
3701 /* pick_call will connect the first incoming call found. the endpoint
3702 * will receivce a MESSAGE_CONNECT.
3704 int match_list(char *list, char *item)
3706 char *end, *next = NULL;
3708 /* no list make matching */
3714 /* eliminate white spaces */
3715 while (*list <= ' ')
3722 /* if end of list is reached, we return */
3723 if (list[0] == '\0')
3725 /* if we have more than one entry (left) */
3726 if ((end = strchr(list, ',')))
3729 next = end = strchr(list, '\0');
3730 while (*(end-1) <= ' ')
3732 /* if string part matches item */
3733 if (!strncmp(list, item, end-list))
3739 void EndpointAppPBX::pick_call(char *extensions)
3741 struct message *message;
3742 struct port_list *portlist;
3744 class EndpointAppPBX *eapp, *found;
3746 class CallPBX *callpbx;
3747 struct call_relation *relation;
3750 /* find an endpoint that is ringing internally or vbox with higher priority */
3753 eapp = apppbx_first;
3756 if (eapp!=this && ea_endpoint->ep_portlist)
3758 portlist = eapp->ea_endpoint->ep_portlist;
3761 if ((port = find_port_id(portlist->port_id)))
3763 if (port->p_type == PORT_TYPE_VBOX_OUT)
3765 if (match_list(extensions, eapp->e_ext.number))
3772 if ((port->p_type==PORT_TYPE_DSS1_NT_OUT || port->p_type==PORT_TYPE_DSS1_TE_OUT)
3773 && port->p_state==PORT_STATE_OUT_ALERTING)
3774 if (match_list(extensions, eapp->e_ext.number))
3779 portlist = portlist->next;
3787 /* if no endpoint found */
3790 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);
3792 set_tone(ea_endpoint->ep_portlist, "cause_10");
3793 message_disconnect_port(ea_endpoint->ep_portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
3794 new_state(EPOINT_STATE_OUT_DISCONNECT);
3799 if (ea_endpoint->ep_call_id)
3801 PERROR("EPOINT(%d) we already have a call. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3804 if (!eapp->ea_endpoint->ep_call_id)
3806 PERROR("EPOINT(%d) ringing endpoint has no call.\n", ea_endpoint->ep_serial);
3809 call = find_call_id(eapp->ea_endpoint->ep_call_id);
3812 PERROR("EPOINT(%d) ringing endpoint's call not found.\n", ea_endpoint->ep_serial);
3815 if (callpbx->c_type != CALL_TYPE_PBX)
3817 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ringing endpoint's call is not a PBX call, so we must reject.\n", ea_endpoint->ep_serial);
3820 callpbx = (class CallPBX *)call;
3821 relation = callpbx->c_relation;
3824 PERROR("EPOINT(%d) ringing endpoint's call has no relation. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3827 while (relation->epoint_id != eapp->ea_endpoint->ep_serial)
3829 relation = relation->next;
3832 PERROR("EPOINT(%d) ringing endpoint's call has no relation to that call. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3837 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found ringing endpoint: %d.\n", ea_endpoint->ep_serial, eapp->ea_endpoint->ep_serial);
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(before)");
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 (active)\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3863 debug_p = debug_p->next;
3868 ea_endpoint->ep_call_id = eapp->ea_endpoint->ep_call_id; /* we get the call */
3869 relation->epoint_id = ea_endpoint->ep_serial; /* the call gets us */
3870 eapp->ea_endpoint->ep_call_id = 0; /* the ringing endpoint will get disconnected */
3872 /* connnecting our endpoint */
3873 new_state(EPOINT_STATE_CONNECT);
3875 set_tone(ea_endpoint->ep_portlist, NULL);
3877 /* now we send a release to the ringing endpoint */
3878 message = message_create(ea_endpoint->ep_call_id, eapp->ea_endpoint->ep_serial, CALL_TO_EPOINT, MESSAGE_RELEASE);
3879 message->param.disconnectinfo.cause = 26; /* non selected user clearing */
3880 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3881 message_put(message);
3883 /* we send a connect to the call with our caller id */
3884 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CONNECT);
3885 SCPY(message->param.connectinfo.id, e_callerinfo.id);
3886 message->param.connectinfo.present = e_callerinfo.present;
3887 message->param.connectinfo.screen = e_callerinfo.screen;
3888 message->param.connectinfo.itype = e_callerinfo.itype;
3889 message->param.connectinfo.ntype = e_callerinfo.ntype;
3890 message_put(message);
3892 /* we send a connect to our port with the remote callerid */
3893 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3894 SCPY(message->param.connectinfo.id, eapp->e_callerinfo.id);
3895 message->param.connectinfo.present = eapp->e_callerinfo.present;
3896 message->param.connectinfo.screen = eapp->e_callerinfo.screen;
3897 message->param.connectinfo.itype = eapp->e_callerinfo.itype;
3898 message->param.connectinfo.ntype = eapp->e_callerinfo.ntype;
3899 /* handle restricted caller ids */
3900 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);
3901 /* display callerid if desired for extension */
3902 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));
3903 message_put(message);
3905 /* we send a connect to the audio path (not for vbox) */
3906 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CHANNEL);
3907 message->param.channel = CHANNEL_STATE_CONNECT;
3908 message_put(message);
3910 /* beeing paranoid, we make call update */
3911 callpbx->c_mixer = 1;
3913 if (options.deb & DEBUG_EPOINT)
3915 class Call *debug_c = call_first;
3916 class Endpoint *debug_e = epoint_first;
3917 class Port *debug_p = port_first;
3919 callpbx_debug(callpbx, "EndpointAppPBX::pick_call(after)");
3921 PDEBUG(DEBUG_EPOINT, "showing all calls:\n");
3924 PDEBUG(DEBUG_EPOINT, "call=%ld\n", debug_c->c_serial);
3925 debug_c = debug_c->next;
3927 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3930 PDEBUG(DEBUG_EPOINT, "ep=%ld, call=%ld\n", debug_e->ep_serial, debug_e->ep_call_id);
3931 debug_e = debug_e->next;
3933 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3936 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3937 debug_p = debug_p->next;
3943 /* join calls (look for a call that is on hold (same isdn interface/terminal))
3945 void EndpointAppPBX::join_call(void)
3947 struct message *message;
3948 struct call_relation *our_relation, *other_relation;
3949 struct call_relation **our_relation_pointer, **other_relation_pointer;
3950 class Call *our_call, *other_call;
3951 class CallPBX *our_callpbx, *other_callpbx;
3952 class EndpointAppPBX *other_eapp; class Endpoint *temp_epoint;
3953 class Port *our_port, *other_port;
3954 class Pdss1 *our_pdss1, *other_pdss1;
3956 /* are we a candidate to join a call */
3957 our_call = find_call_id(ea_endpoint->ep_call_id);
3960 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our call doesn't exist anymore.\n", ea_endpoint->ep_serial);
3963 if (our_call->c_type != CALL_TYPE_PBX)
3965 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: call is not a pbx call.\n", ea_endpoint->ep_serial);
3968 our_callpbx = (class CallPBX *)our_call;
3969 if (!ea_endpoint->ep_portlist)
3971 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
3974 if (!e_ext.number[0])
3976 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
3979 our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
3982 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
3985 if ((our_port->p_type&PORT_CLASS_mISDN_MASK) != PORT_CLASS_mISDN_DSS1)
3987 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not isdn.\n", ea_endpoint->ep_serial);
3990 our_pdss1 = (class Pdss1 *)our_port;
3992 /* find an endpoint that is on hold and has the same mISDNport that we are on */
3993 other_eapp = apppbx_first;
3996 if (other_eapp == this)
3998 other_eapp = other_eapp->next;
4001 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint candiate: (ep%d) terminal='%s' port=%s call=%d.\n", ea_endpoint->ep_serial, other_eapp->ea_endpoint->ep_serial, other_eapp->e_ext.number, (other_eapp->ea_endpoint->ep_portlist)?"YES":"NO", other_eapp->ea_endpoint->ep_call_id);
4002 if (other_eapp->e_ext.number[0] /* has terminal */
4003 && other_eapp->ea_endpoint->ep_portlist /* has port */
4004 && other_eapp->ea_endpoint->ep_call_id) /* has call */
4006 other_port = find_port_id(other_eapp->ea_endpoint->ep_portlist->port_id);
4007 if (other_port) /* port still exists */
4009 if (other_port->p_type==PORT_TYPE_DSS1_NT_OUT
4010 || other_port->p_type==PORT_TYPE_DSS1_NT_IN) /* port is isdn nt-mode */
4012 other_pdss1 = (class Pdss1 *)other_port;
4013 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);
4014 if (other_pdss1->p_m_hold /* port is on hold */
4015 && other_pdss1->p_m_mISDNport == our_pdss1->p_m_mISDNport /* same isdn interface */
4016 && other_pdss1->p_m_d_ces == our_pdss1->p_m_d_ces) /* same tei+sapi */
4020 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of other type!\n", ea_endpoint->ep_serial);
4024 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port doesn't exist enymore.\n", ea_endpoint->ep_serial);
4027 other_eapp = other_eapp->next;
4031 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn interface with port on hold.\n", ea_endpoint->ep_serial);
4034 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port on hold found.\n", ea_endpoint->ep_serial);
4036 /* if we have the same call */
4037 if (other_eapp->ea_endpoint->ep_call_id == ea_endpoint->ep_call_id)
4039 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we an the other have the same call.\n", ea_endpoint->ep_serial);
4042 other_call = find_call_id(other_eapp->ea_endpoint->ep_call_id);
4045 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other call doesn't exist anymore.\n", ea_endpoint->ep_serial);
4048 if (other_call->c_type != CALL_TYPE_PBX)
4050 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other call is not a pbx call.\n", ea_endpoint->ep_serial);
4053 other_callpbx = (class CallPBX *)other_call;
4054 if (our_callpbx->c_partyline && other_callpbx->c_partyline)
4056 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both calls are partylines.\n", ea_endpoint->ep_serial);
4060 /* remove relation to endpoint for call on hold */
4061 other_relation = other_callpbx->c_relation;
4062 other_relation_pointer = &other_callpbx->c_relation;
4063 while(other_relation)
4065 if (other_relation->epoint_id == other_eapp->ea_endpoint->ep_serial)
4067 /* detach other endpoint on hold */
4068 *other_relation_pointer = other_relation->next;
4069 memset(other_relation, 0, sizeof(struct call_relation));
4070 free(other_relation);
4072 other_relation = *other_relation_pointer;
4073 other_eapp->ea_endpoint->ep_call_id = NULL;
4077 /* change call/hold pointer of endpoint to the new call */
4078 temp_epoint = find_epoint_id(other_relation->epoint_id);
4081 if (temp_epoint->ep_call_id == other_call->c_serial)
4082 temp_epoint->ep_call_id = our_call->c_serial;
4085 other_relation_pointer = &other_relation->next;
4086 other_relation = other_relation->next;
4088 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint on hold removed, other enpoints on call relinked (to our call).\n", ea_endpoint->ep_serial);
4090 /* join call relations */
4091 our_relation = our_callpbx->c_relation;
4092 our_relation_pointer = &our_callpbx->c_relation;
4095 our_relation_pointer = &our_relation->next;
4096 our_relation = our_relation->next;
4098 *our_relation_pointer = other_callpbx->c_relation;
4099 other_callpbx->c_relation = NULL;
4100 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) relations joined.\n", ea_endpoint->ep_serial);
4102 /* release endpoint on hold */
4103 message = message_create(other_callpbx->c_serial, other_eapp->ea_endpoint->ep_serial, CALL_TO_EPOINT, MESSAGE_RELEASE);
4104 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */
4105 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
4106 message_put(message);
4108 /* if we are not a partyline, we get partyline state from other call */
4109 our_callpbx->c_partyline += other_callpbx->c_partyline;
4111 /* remove empty call */
4113 PDEBUG(DEBUG_EPOINT, "EPOINT(%d)d-call completely removed!\n");
4115 /* mixer must update */
4116 our_callpbx->c_mixer = 1; /* update mixer flag */
4118 /* we send a retrieve to that endpoint */
4119 // mixer will update the hold-state of the call and send it to the endpoints is changes
4123 /* check if we have an external call
4124 * this is used to check for encryption ability
4126 int EndpointAppPBX::check_external(char **errstr, class Port **port)
4128 struct call_relation *relation;
4130 class CallPBX *callpbx;
4131 class Endpoint *epoint;
4133 /* some paranoia check */
4134 if (!ea_endpoint->ep_portlist)
4136 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we have no port.\n", ea_endpoint->ep_serial);
4137 *errstr = "No Call";
4140 if (!e_ext.number[0])
4142 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we are not internal extension.\n", ea_endpoint->ep_serial);
4143 *errstr = "No Call";
4147 /* check if we have a call with 2 parties */
4148 call = find_call_id(ea_endpoint->ep_call_id);
4151 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have currently no call.\n", ea_endpoint->ep_serial);
4152 *errstr = "No Call";
4155 if (call->c_type != CALL_TYPE_PBX)
4157 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call is nto a pbx call.\n", ea_endpoint->ep_serial);
4158 *errstr = "No PBX Call";
4161 callpbx = (class CallPBX *)call;
4162 relation = callpbx->c_relation;
4165 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call has no relation.\n", ea_endpoint->ep_serial);
4166 *errstr = "No Call";
4169 if (!relation->next)
4171 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call has no 2nd relation.\n", ea_endpoint->ep_serial);
4172 *errstr = "No Call";
4175 if (relation->next->next)
4177 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call has more than two relations.\n", ea_endpoint->ep_serial);
4178 *errstr = "Err: Conference";
4181 if (relation->epoint_id == ea_endpoint->ep_serial)
4183 relation = relation->next;
4184 if (relation->epoint_id == ea_endpoint->ep_serial)
4186 PERROR("EPOINT(%d) SOFTWARE ERROR: both call relations are related to our endpoint.\n", ea_endpoint->ep_serial);
4187 *errstr = "Software Error";
4192 /* check remote port for external call */
4193 epoint = find_epoint_id(relation->epoint_id);
4196 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call has no 2nd endpoint.\n", ea_endpoint->ep_serial);
4197 *errstr = "No Call";
4200 if (!epoint->ep_portlist)
4202 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not port.\n", ea_endpoint->ep_serial);
4203 *errstr = "No Call";
4206 *port = find_port_id(epoint->ep_portlist->port_id);
4209 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has an none existing port.\n", ea_endpoint->ep_serial);
4210 *errstr = "No Call";
4213 if (((*port)->p_type&PORT_CLASS_mISDN_MASK)!=PORT_CLASS_mISDN_DSS1) /* port is not external isdn */
4215 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not an external port.\n", ea_endpoint->ep_serial);
4216 *errstr = "No Ext Call";
4219 if ((*port)->p_state != PORT_STATE_CONNECT)
4221 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint's port is not in connected state.\n", ea_endpoint->ep_serial);
4222 *errstr = "No Ext Connect";
4228 void EndpointAppPBX::logmessage(struct message *message)
4232 char *logtext = "unknown";
4235 if (message->flow != EPOINT_TO_PORT)
4237 PERROR("EPOINT(%d) message not of correct flow type-\n", ea_endpoint->ep_serial);
4241 switch(message->type)
4244 trace_header("SETUP", DIRECTION_OUT);
4245 if (message->param.setup.callerinfo.intern[0])
4246 add_trace("extension", NULL, "%s", message->param.setup.callerinfo.intern);
4247 add_trace("caller id", "number", "%s", numberrize_callerinfo(message->param.setup.callerinfo.id, message->param.setup.callerinfo.ntype));
4248 if (message->param.setup.callerinfo.present == INFO_PRESENT_RESTRICTED)
4249 add_trace("caller id", "present", "restricted");
4250 if (message->param.setup.redirinfo.number[0])
4252 add_trace("redir'ing", "number", "%s", numberrize_callerinfo(message->param.setup.redirinfo.id, message->param.setup.redirinfo.ntype));
4253 if (message->param.setup.redirinfo.present == INFO_PRESENT_RESTRICTED)
4254 add_trace("redir'ing", "present", "restricted");
4256 if (message->param.setup.dialinginfo.number[0])
4257 add_trace("dialing", NULL, "%s", message->param.setup.dialinginfo.number);
4261 case MESSAGE_OVERLAP:
4262 trace_header("SETUP ACKNOWLEDGE", DIRECTION_OUT);
4266 case MESSAGE_PROCEEDING:
4267 trace_header("PROCEEDING", DIRECTION_OUT);
4271 case MESSAGE_ALERTING:
4272 trace_header("ALERTING", DIRECTION_OUT);
4276 case MESSAGE_CONNECT:
4277 trace_header("CONNECT", DIRECTION_OUT);
4278 if (message->param.connectinfo.intern[0])
4279 add_trace("extension", NULL, "%s", message->param.connectinfo.intern);
4280 add_trace("connect id", "number", "%s", numberrize_callerinfo(message->param.connectinfo.id, message->param.connectinfo.ntype));
4281 if (message->param.connectinfo.present == INFO_PRESENT_RESTRICTED)
4282 add_trace("connect id", "present", "restricted");
4286 case MESSAGE_DISCONNECT:
4287 trace_header("DISCONNECT", DIRECTION_OUT);
4288 add_trace("cause", "value", "%d", message->param.disconnectinfo.cause);
4289 add_trace("cause", "location", "%d", message->param.disconnectinfo.location);
4293 case MESSAGE_RELEASE:
4294 trace_header("RELEASE", DIRECTION_OUT);
4295 add_trace("cause", "value", "%d", message->param.disconnectinfo.cause);
4296 add_trace("cause", "location", "%d", message->param.disconnectinfo.location);
4300 case MESSAGE_NOTIFY:
4301 switch(message->param.notifyinfo.notify)
4307 logtext = "USER_SUSPENDED";
4310 logtext = "BEARER_SERVICE_CHANGED";
4313 logtext = "USER_RESUMED";
4316 logtext = "CONFERENCE_ESTABLISHED";
4319 logtext = "CONFERENCE_DISCONNECTED";
4322 logtext = "OTHER_PARTY_ADDED";
4325 logtext = "ISOLATED";
4328 logtext = "REATTACHED";
4331 logtext = "OTHER_PARTY_ISOLATED";
4334 logtext = "OTHER_PARTY_REATTACHED";
4337 logtext = "OTHER_PARTY_SPLIT";
4340 logtext = "OTHER_PARTY_DISCONNECTED";
4343 logtext = "CONFERENCE_FLOATING";
4346 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
4349 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
4352 logtext = "CALL_IS_A_WAITING_CALL";
4355 logtext = "DIVERSION_ACTIVATED";
4358 logtext = "RESERVED_CT_1";
4361 logtext = "RESERVED_CT_2";
4364 logtext = "REVERSE_CHARGING";
4367 logtext = "REMOTE_HOLD";
4370 logtext = "REMOTE_RETRIEVAL";
4373 logtext = "CALL_IS_DIVERTING";
4376 SPRINT(buffer, "%d", message->param.notifyinfo.notify - 0x80);
4380 trace_header("NOTIFY", DIRECTION_OUT);
4381 if (message->param.notifyinfo.notify)
4382 add_trace("indicator", NULL, "%s", logtext);
4383 if (message->param.notifyinfo.number[0])
4385 add_trace("redir'on", "number", "%s", numberrize_callerinfo(message->param.notifyinfo.id, message->param.notifyinfo.ntype));
4386 if (message->param.notifyinfo.present == INFO_PRESENT_RESTRICTED)
4387 add_trace("redir'on", "present", "restricted");
4389 if (message->param.notifyinfo.display[0])
4390 add_trace("display", NULL, "%s", message->param.notifyinfo.display);
4394 case MESSAGE_INFORMATION:
4395 trace_header("INFORMATION", DIRECTION_OUT);
4396 add_trace("dialing", NULL, "%s", message->param.information.number);
4400 case MESSAGE_FACILITY:
4401 trace_header("FACILITY", DIRECTION_OUT);
4406 trace_header("TONE", DIRECTION_OUT);
4407 if (message->param.tone.name[0])
4409 add_trace("directory", NULL, "%s", message->param.tone.dir[0]?message->param.tone.dir:"default");
4410 add_trace("name", NULL, "%s", message->param.tone.name);
4412 add_trace("off", NULL, NULL);
4417 PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message->type);
4421 void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cause, int location, char *display)
4423 struct message *message;
4427 if (!portlist->port_id)
4430 if (!e_connectedmode)
4432 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT);
4433 message->param.disconnectinfo.cause = cause;
4434 message->param.disconnectinfo.location = location;
4436 SCPY(message->param.disconnectinfo.display, display);
4438 SCPY(message->param.disconnectinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4441 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
4443 SCPY(message->param.notifyinfo.display, display);
4445 SCPY(message->param.notifyinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4447 message_put(message);
4448 logmessage(message);