1 /*****************************************************************************\
3 ** Linux Call Router **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
8 ** The EndpointAppPBX implements PBX4Linux **
10 \*****************************************************************************/
15 #include <sys/types.h>
23 class EndpointAppPBX *apppbx_first = NULL;
26 * EndpointAppPBX constructor
28 EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint, int origin) : EndpointApp(epoint, origin)
30 class EndpointAppPBX **apppointer;
32 /* add application to chain */
34 apppointer = &apppbx_first;
36 apppointer = &((*apppointer)->next);
40 memset(&e_ext, 0, sizeof(struct extension));
41 // *************** NOTE: also change value in read_extension() **************
42 e_ext.rights = 4; /* international */
43 e_ext.rx_gain = e_ext.tx_gain = 0;
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.id;
67 // e_join_tone[0] = e_hold_tone[0] = '\0';
68 e_join_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 = 0;
88 e_multipoint_location = 0;
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_join_cause = e_join_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;
129 FATAL("Endpoint not in endpoint's list.\n");
136 * trace header for application
138 void EndpointAppPBX::trace_header(char *name, int direction)
142 char msgtext[sizeof(_trace.name)];
146 /* init trace with given values */
149 numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype),
153 ea_endpoint->ep_serial,
160 /* set new endpoint state
162 void EndpointAppPBX::new_state(int state)
165 if (e_state != state)
167 trace_header("NEW STATE", DIRECTION_NONE);
168 add_trace("state", "old", "%s", state_name[e_state]);
169 add_trace("state", "new", "%s", state_name[state]);
177 /* release join and port (as specified)
179 void EndpointAppPBX::release(int release, int joinlocation, int joincause, int portlocation, int portcause)
181 struct port_list *portlist;
182 struct message *message;
185 /* message to test call */
186 admin_call_response(e_adminid, ADMIN_CALL_RELEASE, "", joincause, joinlocation, 0);
188 /* if a release is pending */
189 if (release==RELEASE_JOIN || release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY)
191 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): do pending release (joincause %d location %d)\n", ea_endpoint->ep_serial, joincause, joinlocation);
192 if (ea_endpoint->ep_join_id)
194 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_RELEASE);
195 message->param.disconnectinfo.cause = joincause;
196 message->param.disconnectinfo.location = joinlocation;
197 message_put(message);
198 ea_endpoint->ep_join_id = 0;
202 if (release != RELEASE_PORT_JOINONLY)
205 join_release(e_hold_id, ea_endpoint->ep_serial, 1, joinlocation, joincause);
210 if (release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY)
212 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release (portcause %d portlocation)\n", ea_endpoint->ep_serial, portcause, portlocation);
213 while((portlist = ea_endpoint->ep_portlist))
215 if (portlist->port_id)
217 SPRINT(cause, "cause_%02x", portcause);
218 set_tone(portlist, cause);
219 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
220 message->param.disconnectinfo.cause = portcause;
221 message->param.disconnectinfo.location = portlocation;
222 message_put(message);
223 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
225 ea_endpoint->free_portlist(portlist);
228 /* if callback is enabled, call back with the given caller id */
231 /* reset some stuff */
232 new_state(EPOINT_STATE_IDLE);
233 memset(&e_connectinfo, 0, sizeof(struct connect_info));
234 memset(&e_redirinfo, 0, sizeof(struct redir_info));
235 e_start = e_stop = 0;
236 e_ruleset = ruleset_main;
238 e_rule = e_ruleset->rule_first;
240 e_action_timeout = 0;
242 e_match_to_action = NULL;
244 e_extdialing = e_dialinginfo.id;
251 e_multipoint_cause = 0;
252 e_multipoint_location = 0;
253 e_dialing_queue[0] = '\0';
255 e_crypt_state = CM_ST_NULL;
256 e_crypt_keyengine_busy = 0;
257 e_crypt_info[0] = '\0';
261 e_tx_state = NOTIFY_STATE_ACTIVE;
262 e_rx_state = NOTIFY_STATE_ACTIVE;
263 e_join_cause = e_join_location = 0;
265 /* the caller info of the callback user */
266 memcpy(&e_callbackinfo, &e_callerinfo, sizeof(e_callbackinfo));
267 memset(&e_dialinginfo, 0, sizeof(e_dialinginfo));
268 /* create dialing by callerinfo */
269 if (e_ext.number[0] && e_extension_interface[0])
271 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to internal: %s interface %s\n", ea_endpoint->ep_serial, e_ext.number, e_extension_interface);
272 /* create callback to the current terminal */
273 SCPY(e_dialinginfo.id, e_ext.number);
274 SCPY(e_dialinginfo.interfaces, e_extension_interface);
275 e_dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
276 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
281 SCPY(e_dialinginfo.id, e_cbto);
284 /* numberrize caller id and use it to dial to the callback */
285 SCPY(e_dialinginfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype));
287 e_dialinginfo.itype = INFO_ITYPE_ISDN;
288 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
289 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to external: %s\n", ea_endpoint->ep_serial, e_dialinginfo.id);
294 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release of epoint itself.\n", ea_endpoint->ep_serial);
295 ea_endpoint->ep_use--; /* when e_lock is 0, the endpoint will be deleted */
301 /* cancel callerid if restricted, unless anon-ignore is enabled at extension or port is of type external (so called police gets caller id :)*/
302 void apply_callerid_restriction(struct extension *ext, char *id, int *ntype, int *present, int *screen, char *extension, char *name)
304 PDEBUG(DEBUG_EPOINT, "id='%s' ntype=%d present=%d screen=%d extension='%s' name='%s'\n", (id)?id:"NULL", (ntype)?*ntype:-1, (present)?*present:-1, (screen)?*screen:-1, (extension)?extension:"NULL", (name)?name:"NULL");
306 /* caller id is not restricted, so we do nothing */
307 if (*present != INFO_PRESENT_RESTRICTED)
310 /* only extensions are restricted */
314 /* if we enabled anonymouse ignore */
315 if (ext->anon_ignore)
318 /* else we remove the caller id */
322 *ntype = INFO_NTYPE_UNKNOWN;
324 // *screen = INFO_SCREEN_USER;
325 // maybe we should not make voip address anonymous
328 // maybe it's no fraud to present extension id
330 // extension[0] = '\0';
335 /* used display message to display callerid as available */
336 char *EndpointAppPBX::apply_callerid_display(char *id, int itype, int ntype, int present, int screen, char *extension, char *name)
338 static char display[81];
341 char *cid = numberrize_callerinfo(id, ntype);
343 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) id='%s' itype=%d ntype=%d present=%d screen=%d extension='%s' name='%s'\n", ea_endpoint->ep_serial, (id)?id:"NULL", itype, ntype, present, screen, (extension)?extension:"NULL", (name)?name:"NULL");
352 /* NOTE: is caller is is not available for this extesion, it has been removed by apply_callerid_restriction already */
354 /* internal extension's caller id */
355 if (extension[0] && e_ext.display_int)
358 SCAT(display, extension);
361 if (itype == INFO_ITYPE_VBOX)
362 SCAT(display, "(vbox)");
364 SCAT(display, "(int)");
367 /* external caller id */
368 if (!extension[0] && e_ext.display_ext)
374 if (present == INFO_PRESENT_RESTRICTED)
375 SCAT(display, "anonymous");
377 SCAT(display, "unknown");
384 /* display if callerid is anonymouse but available due anon-ignore */
385 if (e_ext.display_anon && present==INFO_PRESENT_RESTRICTED)
388 SCAT(display, "unknown");
391 SCAT(display, " anon");
394 /* display if callerid is anonymouse but available due anon-ignore */
395 if (e_ext.display_fake && screen==INFO_SCREEN_USER && present!=INFO_PRESENT_NULL)
401 if (present == INFO_PRESENT_RESTRICTED)
402 SCAT(display, "anonymous");
404 SCAT(display, "unknown");
409 SCAT(display, " fake");
413 if (name[0] && e_ext.display_name)
415 if (!display[0] && cid[0])
426 * uses the current state to notify activity
428 void EndpointAppPBX::notify_active(void)
430 struct port_list *portlist = ea_endpoint->ep_portlist;
431 struct message *message;
436 case NOTIFY_STATE_ACTIVE:
437 /* we are already active, so we don't do anything */
440 case NOTIFY_STATE_SUSPEND:
441 notify = INFO_NOTIFY_USER_RESUMED;
444 set_tone(portlist, NULL);
445 portlist = portlist->next;
447 portlist = ea_endpoint->ep_portlist;
450 case NOTIFY_STATE_HOLD:
451 notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
454 set_tone(portlist, NULL);
455 portlist = portlist->next;
457 portlist = ea_endpoint->ep_portlist;
460 case NOTIFY_STATE_CONFERENCE:
461 notify = INFO_NOTIFY_CONFERENCE_DISCONNECTED;
464 set_tone(portlist, NULL);
465 portlist = portlist->next;
467 portlist = ea_endpoint->ep_portlist;
471 PERROR("unknown e_tx_state = %d\n", e_tx_state);
477 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
478 message->param.notifyinfo.notify = notify;
479 message_put(message);
480 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
481 portlist = portlist->next;
487 * keypad functions during call. one example to use this is to put a call on hold or start a conference
489 void EndpointAppPBX::keypad_function(char digit)
492 /* we must be in a call, in order to send messages to the call */
493 if (e_ext.number[0] == '\0')
495 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) IGNORING keypad received not from extension.\n", ea_endpoint->ep_serial);
501 /* join conference */
503 if (ea_endpoint->ep_join_id == 0)
505 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad received during connect but not during a call.\n", ea_endpoint->ep_serial);
508 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join call with call on hold\n", ea_endpoint->ep_serial);
514 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) shared key encryption selected.\n", ea_endpoint->ep_serial);
518 /* crypt key-exchange */
520 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) key exchange encryption selected.\n", ea_endpoint->ep_serial);
526 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) encryption off selected.\n", ea_endpoint->ep_serial);
531 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) unsupported keypad digit '%c'.\n", ea_endpoint->ep_serial, digit);
536 /* set tone pattern for port */
537 void EndpointAppPBX::set_tone(struct port_list *portlist, char *tone)
539 struct message *message;
544 /* store for suspended processes */
548 if (e_join_pattern /* pattern are provided */
549 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_SETUP)
550 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_OVERLAP)
551 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_IN_PROCEEDING)
552 && !(e_ext.own_alerting && e_state == EPOINT_STATE_IN_ALERTING)
553 && !(e_ext.own_cause && e_state == EPOINT_STATE_IN_DISCONNECT)
554 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_SETUP)
555 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_OVERLAP)
556 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_OUT_PROCEEDING)
557 && !(e_ext.own_alerting && e_state == EPOINT_STATE_OUT_ALERTING)
558 && !(e_ext.own_cause && e_state == EPOINT_STATE_OUT_DISCONNECT)
559 && tone[0] && !!strncmp(tone,"crypt_*",6))
561 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) tone not provided since patterns are available\n", ea_endpoint->ep_serial);
567 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_TONE);
568 SCPY(message->param.tone.dir, e_ext.tones_dir[0]?e_ext.tones_dir:options.tones_dir);
569 SCPY(message->param.tone.name, tone);
570 message_put(message);
571 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
574 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port to notify tone.\n", ea_endpoint->ep_serial);
581 * hunts an mISDNport that is available for an outgoing call
582 * if no ifname was given, any interface that is not an extension
585 struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel)
587 struct interface *interface;
588 struct interface_port *ifport, *ifport_start;
589 struct select_channel *selchannel;
590 struct mISDNport *mISDNport;
593 interface = interface_first;
595 /* first find the given interface or, if not given, one with no extension */
600 /* check for given interface */
603 if (!strcasecmp(interface->name, ifname))
605 /* found explicit interface */
606 trace_header("CHANNEL SELECTION (found interface)", DIRECTION_NONE);
607 add_trace("interface", NULL, "%s", ifname);
614 if (!interface->extension)
616 /* found non extension */
617 trace_header("CHANNEL SELECTION (found non extension interface)", DIRECTION_NONE);
618 add_trace("interface", NULL, "%s", interface->name);
624 interface = interface->next;
628 /* see if interface has ports */
629 if (!interface->ifport)
632 trace_header("CHANNEL SELECTION (interface has no active ports, skipping)", DIRECTION_NONE);
633 add_trace("interface", NULL, "%s", interface->name);
635 interface = interface->next;
639 /* select port by algorithm */
640 ifport_start = interface->ifport;
642 if (interface->hunt == HUNT_ROUNDROBIN)
644 while(ifport_start->next && index<interface->hunt_next)
646 ifport_start = ifport_start->next;
649 trace_header("CHANNEL SELECTION (starting round-robin)", DIRECTION_NONE);
650 add_trace("port", NULL, "%d", ifport_start->portnum);
651 add_trace("position", NULL, "%d", index);
656 ifport = ifport_start;
659 /* see if port is available */
660 if (!ifport->mISDNport)
662 trace_header("CHANNEL SELECTION (port not available, skipping)", DIRECTION_NONE);
663 add_trace("port", NULL, "%d", ifport->portnum);
664 add_trace("position", NULL, "%d", index);
668 mISDNport = ifport->mISDNport;
670 /* see if port is administratively blocked */
673 trace_header("CHANNEL SELECTION (port blocked by admin, skipping)", DIRECTION_NONE);
674 add_trace("port", NULL, "%d", ifport->portnum);
675 add_trace("position", NULL, "%d", index);
680 /* see if link is up on PTP*/
681 if (mISDNport->l2hold && !mISDNport->l2link)
683 trace_header("CHANNEL SELECTION (port holds layer 2, but layer 2 is down, skipping)", DIRECTION_NONE);
684 add_trace("port", NULL, "%d", ifport->portnum);
685 add_trace("position", NULL, "%d", index);
690 /* check for channel form selection list */
692 selchannel = ifport->out_channel;
695 switch(selchannel->channel)
697 case CHANNEL_FREE: /* free channel */
698 if (mISDNport->b_reserved >= mISDNport->b_num)
699 break; /* all channel in use or reserverd */
702 while(i < mISDNport->b_num)
704 if (mISDNport->b_port[i] == NULL)
706 *channel = i+1+(i>=15);
707 trace_header("CHANNEL SELECTION (selecting free channel)", DIRECTION_NONE);
708 add_trace("port", NULL, "%d", ifport->portnum);
709 add_trace("position", NULL, "%d", index);
710 add_trace("channel", NULL, "%d", *channel);
718 trace_header("CHANNEL SELECTION (no channel is 'free')", DIRECTION_NONE);
719 add_trace("port", NULL, "%d", ifport->portnum);
720 add_trace("position", NULL, "%d", index);
724 case CHANNEL_ANY: /* don't ask for channel */
725 if (mISDNport->b_reserved >= mISDNport->b_num)
727 trace_header("CHANNEL SELECTION (cannot ask for 'any' channel, all reserved)", DIRECTION_NONE);
728 add_trace("port", NULL, "%d", ifport->portnum);
729 add_trace("position", NULL, "%d", index);
730 add_trace("total", NULL, "%d", mISDNport->b_num);
731 add_trace("reserved", NULL, "%d", mISDNport->b_reserved);
733 break; /* all channel in use or reserverd */
735 trace_header("CHANNEL SELECTION (using 'any' channel)", DIRECTION_NONE);
736 add_trace("port", NULL, "%d", ifport->portnum);
737 add_trace("position", NULL, "%d", index);
739 *channel = CHANNEL_ANY;
742 case CHANNEL_NO: /* call waiting */
743 trace_header("CHANNEL SELECTION (using 'no' channel, call-waiting)", DIRECTION_NONE);
744 add_trace("port", NULL, "%d", ifport->portnum);
745 add_trace("position", NULL, "%d", index);
747 *channel = CHANNEL_NO;
751 if (selchannel->channel<1 || selchannel->channel==16)
753 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
754 add_trace("port", NULL, "%d", ifport->portnum);
755 add_trace("position", NULL, "%d", index);
756 add_trace("channel", NULL, "%d", selchannel->channel);
758 break; /* invalid channels */
760 i = selchannel->channel-1-(selchannel->channel>=17);
761 if (i >= mISDNport->b_num)
763 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
764 add_trace("port", NULL, "%d", ifport->portnum);
765 add_trace("position", NULL, "%d", index);
766 add_trace("channel", NULL, "%d", selchannel->channel);
767 add_trace("channels", NULL, "%d", mISDNport->b_num);
769 break; /* channel not in port */
771 if (mISDNport->b_port[i] == NULL)
773 *channel = selchannel->channel;
774 trace_header("CHANNEL SELECTION (selecting given channel)", DIRECTION_NONE);
775 add_trace("port", NULL, "%d", ifport->portnum);
776 add_trace("position", NULL, "%d", index);
777 add_trace("channel", NULL, "%d", *channel);
784 break; /* found channel */
785 selchannel = selchannel->next;
788 /* if channel was found, return mISDNport and channel */
791 /* setting next port to start next time */
792 if (interface->hunt == HUNT_ROUNDROBIN)
797 interface->hunt_next = index;
803 trace_header("CHANNEL SELECTION (skipping, no channel found)", DIRECTION_NONE);
804 add_trace("port", NULL, "%d", ifport->portnum);
805 add_trace("position", NULL, "%d", index);
809 /* go next port, until all ports are checked */
811 ifport = ifport->next;
815 ifport = interface->ifport;
817 if (ifport != ifport_start)
820 return(NULL); /* no port found */
823 /* outgoing setup to port(s)
824 * ports will be created and a setup is sent if everything is ok. otherwhise
825 * the endpoint is destroyed.
827 void EndpointAppPBX::out_setup(void)
829 struct dialing_info dialinginfo;
831 // class pdss1 *pdss1;
832 struct port_list *portlist;
833 struct message *message;
835 int cause = CAUSE_RESSOURCEUNAVAIL;
838 struct mISDNport *mISDNport;
841 class EndpointAppPBX *atemp;
842 // char allowed_ports[256];
844 char ifname[sizeof(e_ext.interfaces)],
846 struct port_settings port_settings;
850 /* create settings for creating port */
851 memset(&port_settings, 0, sizeof(port_settings));
853 SCPY(port_settings.tones_dir, e_ext.tones_dir);
855 SCPY(port_settings.tones_dir, options.tones_dir);
856 port_settings.no_seconds = e_ext.no_seconds;
858 /* 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 */
860 /* check what dialinginfo.itype we got */
861 switch(e_dialinginfo.itype)
863 /* *********************** call to extension or vbox */
864 case INFO_ITYPE_ISDN_EXTENSION:
865 /* check if we deny incoming calls when we use an extension */
866 if (e_ext.noknocking)
868 atemp = apppbx_first;
872 if (!strcmp(atemp->e_ext.number, e_ext.number))
878 PERROR("EPOINT(%d) noknocking and currently a call\n", ea_endpoint->ep_serial);
879 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYSPE_ join, port */
880 return; /* must exit here */
883 /* FALL THROUGH !!!! */
884 case INFO_ITYPE_VBOX:
885 /* get dialed extension's info */
886 // SCPY(exten, e_dialinginfo.id);
887 // if (strchr(exten, ','))
888 // *strchr(exten, ',') = '\0';
889 // if (!read_extension(&e_ext, exten))
890 if (!read_extension(&e_ext, e_dialinginfo.id))
892 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) extension %s not configured\n", ea_endpoint->ep_serial, e_dialinginfo.id);
893 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
894 return; /* must exit here */
897 if (e_dialinginfo.itype == INFO_ITYPE_VBOX)
899 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing directly to VBOX\n", ea_endpoint->ep_serial);
904 /* string from unconditional call forward (cfu) */
908 /* present to forwarded party */
909 if (e_ext.anon_ignore && e_callerinfo.id[0])
911 e_callerinfo.present = INFO_PRESENT_ALLOWED;
913 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
917 /* string from busy call forward (cfb) */
921 class EndpointAppPBX *checkapp = apppbx_first;
924 if (checkapp != this) /* any other endpoint except our own */
926 if (!strcmp(checkapp->e_ext.number, e_ext.number))
928 /* present to forwarded party */
929 if (e_ext.anon_ignore && e_callerinfo.id[0])
931 e_callerinfo.present = INFO_PRESENT_ALLOWED;
933 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
937 checkapp = checkapp->next;
941 /* string from no-response call forward (cfnr) */
945 /* when cfnr is done, out_setup() will setup the call */
948 /* present to forwarded party */
949 if (e_ext.anon_ignore && e_callerinfo.id[0])
951 e_callerinfo.present = INFO_PRESENT_ALLOWED;
955 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
957 e_cfnr_release = now + e_ext.cfnr_delay;
958 e_cfnr_call = now + e_ext.cfnr_delay + 1; /* call one second after release */
959 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);
963 /* call to all internal interfaces */
964 p = e_ext.interfaces;
965 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) generating multiple joins for extension %s to interfaces %s\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
969 while(*p!=',' && *p!='\0')
974 /* found interface */
975 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
976 /* hunt for mISDNport and create Port */
977 mISDNport = hunt_port(ifname, &channel);
980 trace_header("INTERFACE (not found or busy)", DIRECTION_NONE);
981 add_trace("interface", NULL, "%s", ifname);
985 /* creating INTERNAL port */
986 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
987 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force);
989 FATAL("No memory for DSS1 Port instance\n");
990 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
991 memset(&dialinginfo, 0, sizeof(dialinginfo));
992 SCPY(dialinginfo.id, e_dialinginfo.id);
993 dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
994 dialinginfo.ntype = e_dialinginfo.ntype;
995 /* create port_list relation */
996 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
999 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1001 goto check_anycall_intern;
1003 /* directory.list */
1004 if (e_callerinfo.id[0] && e_ext.display_name)
1006 dirname = parse_directory(e_callerinfo.id, e_callerinfo.ntype);
1008 SCPY(e_callerinfo.name, dirname);
1010 // dss1 = (class Pdss1 *)port;
1012 //printf("INTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1013 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1014 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1015 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1016 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1017 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1018 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1019 //terminal if (e_dialinginfo.id)
1020 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1021 /* handle restricted caller ids */
1022 apply_callerid_restriction(&e_ext, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
1023 apply_callerid_restriction(&e_ext, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, 0, message->param.setup.redirinfo.extension, NULL);
1024 /* display callerid if desired for extension */
1025 SCPY(message->param.setup.callerinfo.display, apply_callerid_display(message->param.setup.callerinfo.id, message->param.setup.callerinfo.itype, message->param.setup.callerinfo.ntype, message->param.setup.callerinfo.present, message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name));
1026 //printf("\n\ndisplay = %s\n\n\n",message->param.setup.callerinfo.display);
1027 /* use cnip, if enabld */
1028 // if (!e_ext.centrex)
1029 // message->param.setup.callerinfo.name[0] = '\0';
1030 /* screen clip if prefix is required */
1031 if (message->param.setup.callerinfo.id[0] && e_ext.clip_prefix[0])
1033 SCPY(message->param.setup.callerinfo.id, e_ext.clip_prefix);
1034 SCAT(message->param.setup.callerinfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype));
1035 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1037 /* use internal caller id */
1038 if (e_callerinfo.extension[0] && (message->param.setup.callerinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
1040 SCPY(message->param.setup.callerinfo.id, e_callerinfo.extension);
1041 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1043 message_put(message);
1044 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1048 /* string from parallel call forward (cfp) */
1052 if (e_ext.anon_ignore && e_callerinfo.id[0])
1054 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1058 vbox_only: /* entry point for answering machine only */
1059 cfu_only: /* entry point for cfu */
1060 cfb_only: /* entry point for cfb */
1061 cfnr_only: /* entry point for cfnr */
1062 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call extension %s for external destiantion(s) '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
1067 /* only if vbox should be dialed, and terminal is given */
1068 if (!strcmp(p, "vbox") && e_ext.number[0])
1070 /* go to the end of p */
1073 /* answering vbox call */
1074 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) answering machine\n", ea_endpoint->ep_serial);
1076 if (!(port = new VBoxPort(PORT_TYPE_VBOX_OUT, &port_settings)))
1077 FATAL("No memory for VBOX Port instance\n");
1078 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocated port %s\n", ea_endpoint->ep_serial, port->p_name);
1079 UCPY(cfp, e_ext.number); /* cfp or any other direct forward/vbox */
1083 while(*p!=',' && *p!='\0')
1088 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cfp external %s\n", ea_endpoint->ep_serial, cfp);
1089 /* hunt for mISDNport and create Port */
1090 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1093 /* creating EXTERNAL port*/
1094 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1095 if (!(port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force)))
1096 FATAL("No memory for DSS1 Port instance\n");
1097 earlyb = mISDNport->earlyb;
1101 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1102 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1108 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port found or created, which is idle.\n", ea_endpoint->ep_serial);
1109 goto check_anycall_intern;
1111 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found or created port %s\n", ea_endpoint->ep_serial, port->p_name);
1112 memset(&dialinginfo, 0, sizeof(dialinginfo));
1113 SCPY(dialinginfo.id, cfp);
1114 dialinginfo.itype = INFO_ITYPE_ISDN;
1115 dialinginfo.ntype = e_dialinginfo.ntype;
1116 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
1119 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1121 goto check_anycall_intern;
1123 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1124 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1125 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1126 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1127 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1128 /* if clip is hidden */
1129 if (e_ext.clip==CLIP_HIDE && port->p_type!=PORT_TYPE_VBOX_OUT)
1131 SCPY(message->param.setup.callerinfo.id, e_ext.callerid);
1132 SCPY(message->param.setup.callerinfo.extension, e_ext.number);
1133 message->param.setup.callerinfo.ntype = e_ext.callerid_type;
1134 message->param.setup.callerinfo.present = e_ext.callerid_present;
1136 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1137 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1138 //terminal if (e_dialinginfo.id)
1139 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1140 /* handle restricted caller ids */
1141 apply_callerid_restriction(&e_ext, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
1142 apply_callerid_restriction(&e_ext, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, 0, message->param.setup.redirinfo.extension, NULL);
1143 /* display callerid if desired for extension */
1144 SCPY(message->param.setup.callerinfo.display, apply_callerid_display(message->param.setup.callerinfo.id, message->param.setup.callerinfo.itype, message->param.setup.callerinfo.ntype, message->param.setup.callerinfo.present, message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name));
1145 message_put(message);
1146 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1150 check_anycall_intern:
1151 /* now we have all ports created */
1154 trace_header("INTERFACE (no extension's interface)", DIRECTION_NONE);
1156 if (!ea_endpoint->ep_join_id)
1158 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1159 return; /* must exit here */
1163 /* *********************** external call */
1165 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id);
1166 /* call to extenal interfaces */
1167 p = e_dialinginfo.id;
1171 while(*p!=',' && *p!='\0')
1172 SCCAT(number, *p++);
1176 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");
1177 /* hunt for mISDNport and create Port */
1178 /* hunt for mISDNport and create Port */
1179 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1182 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1183 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1185 goto check_anycall_extern;
1187 /* creating EXTERNAL port*/
1188 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1189 if (!(port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force)))
1190 FATAL("No memory for DSS1 Port instance\n");
1191 earlyb = mISDNport->earlyb;
1192 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
1193 memset(&dialinginfo, 0, sizeof(dialinginfo));
1194 SCPY(dialinginfo.id, number);
1195 dialinginfo.itype = INFO_ITYPE_ISDN;
1196 dialinginfo.ntype = e_dialinginfo.ntype;
1197 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
1200 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1202 goto check_anycall_extern;
1204 // dss1 = (class Pdss1 *)port;
1205 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1206 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1207 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1208 SCPY(message->param.setup.dialinginfo.id, number);
1209 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1210 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1211 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1212 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1213 //terminal if (e_dialinginfo.id)
1214 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1215 /* handle restricted caller ids */
1216 apply_callerid_restriction(&e_ext, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
1217 apply_callerid_restriction(&e_ext, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, 0, message->param.setup.redirinfo.extension, NULL);
1218 /* display callerid if desired for extension */
1219 SCPY(message->param.setup.callerinfo.display, apply_callerid_display(message->param.setup.callerinfo.id, message->param.setup.callerinfo.itype, message->param.setup.callerinfo.ntype, message->param.setup.callerinfo.present, message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name));
1220 message_put(message);
1221 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1225 check_anycall_extern:
1226 /* now we have all ports created */
1229 trace_header("INTERFACE (no free ports found)", DIRECTION_NONE);
1231 if (!ea_endpoint->ep_join_id)
1233 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1234 return; /* must exit here */
1242 /* handler for endpoint
1246 int EndpointAppPBX::handler(void)
1248 if (e_crypt_state!=CM_ST_NULL)
1253 /* process answering machine (play) handling */
1256 if (e_action->index == ACTION_VBOX_PLAY)
1259 /* process action timeout */
1260 if (e_action_timeout)
1261 if (now_d >= e_action_timeout)
1263 if (e_state!=EPOINT_STATE_CONNECT)
1266 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current action timed out.\n", ea_endpoint->ep_serial);
1267 e_multipoint_cause = 0;
1268 e_multipoint_location = 0;
1269 new_state(EPOINT_STATE_IN_OVERLAP);
1272 return(1); /* we must exit, because our endpoint might be gone */
1274 e_action_timeout = 0;
1277 /* process action timeout */
1278 if (e_match_timeout)
1279 if (now_d >= e_match_timeout)
1282 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we got a match timeout.\n", ea_endpoint->ep_serial);
1284 return(1); /* we must exit, because our endpoint might be gone */
1289 /* process redialing (epoint redials to port) */
1292 if (now_d >= e_redial)
1295 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial.\n", ea_endpoint->ep_serial);
1297 new_state(EPOINT_STATE_OUT_SETUP);
1298 /* call special setup routine */
1305 /* process powerdialing (epoint redials to epoint) */
1306 if (e_powerdialing > 0)
1308 if (now_d >= e_powerdialing)
1310 e_powerdialing = -1; /* leave power dialing on */
1311 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial of powerdial.\n", ea_endpoint->ep_serial);
1314 e_ruleset = ruleset_main;
1316 e_rule = e_ruleset->rule_first;
1318 new_state(EPOINT_STATE_IN_OVERLAP);
1324 /* process call forward no response */
1327 struct port_list *portlist;
1328 struct message *message;
1330 if (now >= e_cfnr_release)
1332 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-no-response time has expired, hanging up.\n", ea_endpoint->ep_serial);
1335 /* release all ports */
1336 while((portlist = ea_endpoint->ep_portlist))
1338 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1339 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
1340 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1341 message_put(message);
1342 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1343 ea_endpoint->free_portlist(portlist);
1346 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1347 message->param.audiopath = CHANNEL_STATE_HOLD;
1348 message_put(message);
1349 /* indicate no patterns */
1350 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1351 message_put(message);
1352 /* set setup state, since we have no response from the new join */
1353 new_state(EPOINT_STATE_OUT_SETUP);
1358 if (now >= e_cfnr_call)
1360 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-busy time has expired, calling the forwarded number: %s.\n", ea_endpoint->ep_serial, e_ext.cfnr);
1366 /* handle connection to user */
1367 if (e_state == EPOINT_STATE_IDLE)
1369 /* epoint is idle, check callback */
1371 if (now_d >= e_callback)
1373 e_callback = 0; /* done with callback */
1374 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting callback.\n", ea_endpoint->ep_serial);
1375 new_state(EPOINT_STATE_OUT_SETUP);
1381 /* check for password timeout */
1383 if (e_action->index==ACTION_PASSWORD || e_action->index==ACTION_PASSWORD_WRITE)
1385 struct port_list *portlist;
1387 if (now >= e_password_timeout)
1389 e_ruleset = ruleset_main;
1391 e_rule = e_ruleset->rule_first;
1393 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) password timeout %s\n", ea_endpoint->ep_serial, e_extdialing);
1394 trace_header("PASSWORD timeout", DIRECTION_NONE);
1396 e_connectedmode = 0;
1398 new_state(EPOINT_STATE_OUT_DISCONNECT);
1399 portlist = ea_endpoint->ep_portlist;
1402 message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
1403 set_tone(portlist, "cause_10");
1413 /* doing a hookflash */
1414 void EndpointAppPBX::hookflash(void)
1418 /* be sure that we are active */
1420 e_tx_state = NOTIFY_STATE_ACTIVE;
1422 trace_header("HOOKFLASH DTMF", DIRECTION_NONE);
1424 if (ea_endpoint->ep_use > 1)
1426 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot hooflash while child process is running.\n", ea_endpoint->ep_serial);
1429 /* dialtone after pressing the hash key */
1430 process_hangup(e_join_cause, e_join_location);
1431 e_multipoint_cause = 0;
1432 e_multipoint_location = 0;
1433 port = find_port_id(ea_endpoint->ep_portlist->port_id);
1436 port->set_echotest(0);
1438 if (ea_endpoint->ep_join_id)
1440 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1442 e_ruleset = ruleset_main;
1444 e_rule = e_ruleset->rule_first;
1446 new_state(EPOINT_STATE_IN_OVERLAP);
1447 e_connectedmode = 1;
1448 SCPY(e_dialinginfo.id, e_ext.prefix);
1449 e_extdialing = e_dialinginfo.id;
1451 if (e_dialinginfo.id[0])
1453 set_tone(ea_endpoint->ep_portlist, "dialing");
1457 set_tone(ea_endpoint->ep_portlist, "dialpbx");
1464 /* messages from port
1466 /* port MESSAGE_SETUP */
1467 void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, union parameter *param)
1469 struct message *message;
1471 int writeext; /* flags need to write extension after modification */
1473 struct interface *interface;
1475 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1477 portlist->port_type = param->setup.port_type;
1478 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
1479 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
1480 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
1481 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
1482 e_dtmf = param->setup.dtmf;
1483 /* screen incoming caller id */
1484 interface = interface_first;
1487 if (!strcmp(e_callerinfo.interface, interface->name))
1491 interface = interface->next;
1494 do_screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface);
1496 /* process extension */
1497 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1499 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is extension\n", ea_endpoint->ep_serial);
1500 /* port makes call from extension */
1501 SCPY(e_callerinfo.extension, e_callerinfo.id);
1502 SCPY(e_ext.number, e_callerinfo.extension);
1503 SCPY(e_extension_interface, e_callerinfo.interface);
1506 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is external or voip\n", ea_endpoint->ep_serial);
1509 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1511 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1513 /* get extension's info about caller */
1514 if (!read_extension(&e_ext, e_ext.number))
1516 /* extension doesn't exist */
1517 trace_header("EXTENSION (not created)", DIRECTION_IN);
1518 add_trace("extension", NULL, "%s", e_ext.number);
1520 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
1521 new_state(EPOINT_STATE_OUT_DISCONNECT);
1522 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
1523 e_ext.number[0] = '\0'; /* no terminal */
1528 /* put prefix (next) in front of e_dialinginfo.id */
1531 SPRINT(buffer, "%s%s", e_ext.next, e_dialinginfo.id);
1532 SCPY(e_dialinginfo.id, buffer);
1533 e_ext.next[0] = '\0';
1535 } else if (e_ext.prefix[0])
1537 SPRINT(buffer, "%s%s", e_ext.prefix, e_dialinginfo.id);
1538 SCPY(e_dialinginfo.id, buffer);
1541 /* screen caller id by extension's config */
1542 e_callerinfo.screen = INFO_SCREEN_NETWORK;
1544 SCPY(e_callerinfo.name, e_ext.name);
1545 /* use caller id (or if exist: id_next_call) for this call */
1546 if (e_ext.id_next_call_present >= 0)
1548 SCPY(e_callerinfo.id, e_ext.id_next_call);
1549 /* if we restrict the pesentation */
1550 if (e_ext.id_next_call_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1551 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1552 else e_callerinfo.present = e_ext.id_next_call_present;
1553 e_callerinfo.ntype = e_ext.id_next_call_type;
1554 e_ext.id_next_call_present = -1;
1558 SCPY(e_callerinfo.id, e_ext.callerid);
1559 /* if we restrict the pesentation */
1560 if (e_ext.callerid_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1561 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1562 else e_callerinfo.present = e_ext.callerid_present;
1563 e_callerinfo.ntype = e_ext.callerid_type;
1566 /* extension is written */
1568 write_extension(&e_ext, e_ext.number);
1570 /* set volume of rx and tx */
1571 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1572 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
1574 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
1575 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
1576 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
1577 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
1578 message_put(message);
1581 /* start recording if enabled */
1582 if (e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO))
1584 /* check if we are a terminal */
1585 if (e_ext.number[0] == '\0')
1586 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
1589 port = find_port_id(portlist->port_id);
1591 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
1596 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from external port\n", ea_endpoint->ep_serial);
1597 /* no terminal identification */
1598 e_ext.number[0] = '\0';
1599 e_extension_interface[0] = '\0';
1600 memset(&e_ext, 0, sizeof(e_ext));
1601 e_ext.rights = 4; /* right to dial internat */
1605 e_ruleset = ruleset_main;
1607 e_rule = e_ruleset->rule_first;
1609 e_extdialing = e_dialinginfo.id;
1610 new_state(EPOINT_STATE_IN_SETUP);
1611 if (e_dialinginfo.id[0])
1613 set_tone(portlist, "dialing");
1616 if (e_ext.number[0])
1617 set_tone(portlist, "dialpbx");
1619 set_tone(portlist, "dialtone");
1622 if (e_state == EPOINT_STATE_IN_SETUP)
1624 /* request MORE info, if not already at higher state */
1625 new_state(EPOINT_STATE_IN_OVERLAP);
1626 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_OVERLAP);
1627 message_put(message);
1628 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1632 /* port MESSAGE_INFORMATION */
1633 void EndpointAppPBX::port_information(struct port_list *portlist, int message_type, union parameter *param)
1635 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1639 /* turn off dtmf detection, in case dtmf is sent with keypad information */
1642 trace_header("DTMF (disabling due to keypad)", DIRECTION_IN);
1647 /* if vbox_play is done, the information are just used as they come */
1649 if (e_action->index == ACTION_VBOX_PLAY)
1651 /* concat dialing string */
1652 SCAT(e_dialinginfo.id, param->information.id);
1657 /* keypad when disconnect but in connected mode */
1658 if (e_state==EPOINT_STATE_OUT_DISCONNECT && e_connectedmode)
1660 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received after disconnect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1661 /* processing keypad function */
1662 if (param->information.id[0] == '0')
1669 /* keypad when connected */
1670 if (e_state == EPOINT_STATE_CONNECT)
1674 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1675 /* processing keypad function */
1676 if (param->information.id[0] == '0')
1680 if (param->information.id[0])
1681 keypad_function(param->information.id[0]);
1684 if (e_ext.number[0])
1685 trace_header("KEYPAD (not enabled by extension's settings)", DIRECTION_IN);
1687 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1692 if (e_state != EPOINT_STATE_IN_OVERLAP)
1694 if (e_ext.number[0])
1695 trace_header("KEYPAD (ignored, not connected and not dialing)", DIRECTION_IN);
1697 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1701 if (!param->information.id[0])
1703 if (e_dialinginfo.id[0]=='\0' && !e_action)
1705 set_tone(portlist, "dialing");
1708 if (e_action->index==ACTION_OUTDIAL
1709 || e_action->index==ACTION_EXTERNAL)
1712 set_tone(portlist, "dialing");
1713 else if (!e_extdialing[0])
1714 set_tone(portlist, "dialing");
1716 /* concat dialing string */
1717 SCAT(e_dialinginfo.id, param->information.id);
1721 /* port MESSAGE_DTMF */
1722 void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
1724 /* only if dtmf detection is enabled */
1727 trace_header("DTMF (disabled)", DIRECTION_IN);
1731 trace_header("DTMF", DIRECTION_IN);
1732 add_trace("digit", NULL, "%c", param->dtmf);
1736 NOTE: vbox is now handled due to overlap state
1737 /* if vbox_play is done, the dtmf digits are just used as they come */
1739 if (e_action->index == ACTION_VBOX_PLAY)
1741 /* concat dialing string */
1742 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id))
1744 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1745 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1748 /* continue to process *X# sequences */
1752 /* check for *X# sequence */
1753 if (e_state == EPOINT_STATE_CONNECT)
1755 if (e_dtmf_time+3 < now)
1757 /* the last digit was too far in the past to be a sequence */
1758 if (param->dtmf == '*')
1759 /* only start is allowed in the sequence */
1765 /* we have a sequence of digits, see what we got */
1766 if (param->dtmf == '*')
1768 else if (param->dtmf>='0' && param->dtmf<='9')
1770 /* we need to have a star before we receive the digit of the sequence */
1771 if (e_dtmf_last == '*')
1772 e_dtmf_last = param->dtmf;
1773 } else if (param->dtmf == '#')
1776 if (e_dtmf_last>='0' && e_dtmf_last<='9')
1778 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf sequence *%c# detected.\n", ea_endpoint->ep_serial, e_dtmf_last);
1779 if (e_dtmf_last == '0')
1784 /* processing keypad function */
1786 keypad_function(e_dtmf_last);
1792 /* set last time of dtmf */
1797 /* check for ## hookflash during dialing */
1799 if (e_action->index==ACTION_PASSWORD
1800 || e_action->index==ACTION_PASSWORD_WRITE)
1802 if (param->dtmf=='#') /* current digit is '#' */
1804 if (e_state==EPOINT_STATE_IN_DISCONNECT
1805 || (e_state!=EPOINT_STATE_CONNECT && e_dtmf_time+3>=now && e_dtmf_last=='#')) /* when disconnected, just #. when dialing, ##. */
1822 /* dialing using dtmf digit */
1823 if (e_state==EPOINT_STATE_IN_OVERLAP)// && e_state==e_connectedmode)
1825 if (e_dialinginfo.id[0]=='\0' && !e_action)
1827 set_tone(portlist, "dialing");
1829 /* concat dialing string */
1830 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id))
1832 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1833 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1839 /* port MESSAGE_CRYPT */
1840 void EndpointAppPBX::port_crypt(struct port_list *portlist, int message_type, union parameter *param)
1842 /* send crypt response to cryptman */
1843 if (param->crypt.type == CR_MESSAGE_IND)
1844 cryptman_msg2man(param->crypt.data, param->crypt.len);
1846 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
1849 /* port MESSAGE_OVERLAP */
1850 void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, union parameter *param)
1852 struct message *message;
1854 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1856 /* signal to call tool */
1857 admin_call_response(e_adminid, ADMIN_CALL_SETUP_ACK, "", 0, 0, 0);
1859 if (e_dialing_queue[0] && portlist)
1861 /* send what we have not dialed yet, because we had no setup complete */
1862 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing pending digits: '%s'\n", ea_endpoint->ep_serial, e_dialing_queue);
1863 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
1864 SCPY(message->param.information.id, e_dialing_queue);
1865 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
1866 message_put(message);
1867 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
1868 e_dialing_queue[0] = '\0';
1870 /* check if pattern is available */
1871 if (!ea_endpoint->ep_portlist->next && portlist->early_b) /* one port_list relation and tones available */
1873 /* indicate patterns */
1874 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1875 message_put(message);
1877 /* connect audio, if not already */
1878 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1879 message->param.audiopath = CHANNEL_STATE_CONNECT;
1880 message_put(message);
1883 /* indicate no patterns */
1884 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1885 message_put(message);
1887 /* disconnect audio, if not already */
1888 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1889 message->param.audiopath = CHANNEL_STATE_HOLD;
1890 message_put(message);
1892 new_state(EPOINT_STATE_OUT_OVERLAP);
1893 /* if we are in a join */
1894 if (ea_endpoint->ep_join_id)
1896 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1897 memcpy(&message->param, param, sizeof(union parameter));
1898 message_put(message);
1902 /* port MESSAGE_PROCEEDING */
1903 void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_type, union parameter *param)
1905 struct message *message;
1907 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1909 /* signal to call tool */
1910 admin_call_response(e_adminid, ADMIN_CALL_PROCEEDING, "", 0, 0, 0);
1912 e_state = EPOINT_STATE_OUT_PROCEEDING;
1913 /* check if pattern is availatle */
1914 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
1916 /* indicate patterns */
1917 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1918 message_put(message);
1920 /* connect audio, if not already */
1921 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1922 message->param.audiopath = CHANNEL_STATE_CONNECT;
1923 message_put(message);
1926 /* indicate no patterns */
1927 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1928 message_put(message);
1930 /* disconnect audio, if not already */
1931 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1932 message->param.audiopath = CHANNEL_STATE_HOLD;
1933 message_put(message);
1935 /* if we are in a call */
1936 if (ea_endpoint->ep_join_id)
1938 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1939 memcpy(&message->param, param, sizeof(union parameter));
1940 message_put(message);
1944 /* port MESSAGE_ALERTING */
1945 void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type, union parameter *param)
1947 struct message *message;
1949 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1951 /* signal to call tool */
1952 admin_call_response(e_adminid, ADMIN_CALL_ALERTING, "", 0, 0, 0);
1954 new_state(EPOINT_STATE_OUT_ALERTING);
1955 /* check if pattern is available */
1956 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
1958 /* indicate patterns */
1959 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1960 message_put(message);
1962 /* connect audio, if not already */
1963 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1964 message->param.audiopath = CHANNEL_STATE_CONNECT;
1965 message_put(message);
1968 /* indicate no patterns */
1969 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1970 message_put(message);
1972 /* disconnect audio, if not already */
1973 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1974 message->param.audiopath = CHANNEL_STATE_HOLD;
1975 message_put(message);
1977 /* if we are in a call */
1978 if (ea_endpoint->ep_join_id)
1980 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1981 memcpy(&message->param, param, sizeof(union parameter));
1982 message_put(message);
1986 /* port MESSAGE_CONNECT */
1987 void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, union parameter *param)
1989 struct message *message;
1991 unsigned long port_id = portlist->port_id;
1992 struct port_list *tportlist;
1994 struct interface *interface;
1996 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1998 /* signal to call tool */
1999 admin_call_response(e_adminid, ADMIN_CALL_CONNECT, numberrize_callerinfo(param->connectinfo.id,param->connectinfo.ntype), 0, 0, 0);
2001 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_connectinfo));
2002 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (start)\n", ea_endpoint->ep_serial);
2003 while(ea_endpoint->ep_portlist->next) /* as long as we have at least two ports */
2005 tportlist = ea_endpoint->ep_portlist;
2006 if (tportlist->port_id == port_id) /* if the first portlist is the calling one, the second must be a different one */
2007 tportlist = tportlist->next;
2008 if (tportlist->port_id == port_id)
2009 FATAL("EPOINT(%d) this should not happen since the portlist list must not have two links to the same port - exitting.\n");
2010 message = message_create(ea_endpoint->ep_serial, tportlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2011 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
2012 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2013 message_put(message);
2014 logmessage(message->type, &message->param, tportlist->port_id, DIRECTION_OUT);
2015 ea_endpoint->free_portlist(tportlist);
2017 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (end)\n", ea_endpoint->ep_serial);
2021 /* screen incoming connected id */
2022 interface = interface_first;
2025 if (!strcmp(e_connectinfo.interface, interface->name))
2029 interface = interface->next;
2032 do_screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface);
2034 /* screen connected name */
2036 SCPY(e_connectinfo.name, e_ext.name);
2038 /* add internal id to colp */
2039 SCPY(e_connectinfo.extension, e_ext.number);
2041 /* we store the connected port number */
2042 SCPY(e_extension_interface, e_connectinfo.interface);
2044 /* for internal and am calls, we get the extension's id */
2045 if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE)
2047 SCPY(e_connectinfo.id, e_ext.callerid);
2048 SCPY(e_connectinfo.extension, e_ext.number);
2049 e_connectinfo.itype = INFO_ITYPE_ISDN_EXTENSION;
2050 e_connectinfo.ntype = e_ext.callerid_type;
2051 e_connectinfo.present = e_ext.callerid_present;
2053 if (portlist->port_type==PORT_TYPE_VBOX_OUT)
2055 e_connectinfo.itype = INFO_ITYPE_VBOX;
2056 e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2059 new_state(EPOINT_STATE_CONNECT);
2061 /* set volume of rx and tx */
2062 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
2064 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2065 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2066 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
2067 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
2068 message_put(message);
2071 e_cfnr_call = e_cfnr_release = 0;
2072 if (e_ext.number[0])
2073 e_dtmf = 1; /* allow dtmf */
2076 /* other calls with no caller id (or not available for the extension) and force colp */
2077 if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE)
2079 e_connectinfo.present = INFO_PRESENT_NOTAVAIL;
2080 if (portlist->port_type==PORT_TYPE_DSS1_TE_OUT || portlist->port_type==PORT_TYPE_DSS1_NT_OUT) /* external extension answered */
2082 port = find_port_id(portlist->port_id);
2085 SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.id, &e_connectinfo.ntype));
2086 e_connectinfo.present = INFO_PRESENT_ALLOWED;
2091 /* send connect to join */
2092 if (ea_endpoint->ep_join_id)
2094 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2095 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
2096 message_put(message);
2098 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2099 message->param.audiopath = CHANNEL_STATE_CONNECT;
2100 message_put(message);
2101 } else if (!e_adminid)
2104 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have a callback, so we create a call with cbcaller: \"%s\".\n", ea_endpoint->ep_serial, e_cbcaller);
2105 SCPY(e_ext.number, e_cbcaller);
2106 new_state(EPOINT_STATE_IN_OVERLAP);
2107 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) callback from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2109 /* get extension's info about terminal */
2110 if (!read_extension(&e_ext, e_ext.number))
2112 /* extension doesn't exist */
2113 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2114 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
2115 new_state(EPOINT_STATE_OUT_DISCONNECT);
2116 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
2120 /* put prefix in front of e_cbdialing */
2121 SPRINT(buffer, "%s%s", e_ext.prefix, e_cbdialing);
2122 SCPY(e_dialinginfo.id, buffer);
2123 e_dialinginfo.itype = INFO_ITYPE_ISDN;
2124 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
2126 /* use caller id (or if exist: id_next_call) for this call */
2127 e_callerinfo.screen = INFO_SCREEN_NETWORK;
2128 SCPY(e_callerinfo.extension, e_ext.number);
2129 if (e_ext.id_next_call_present >= 0)
2131 SCPY(e_callerinfo.id, e_ext.id_next_call);
2132 e_callerinfo.present = e_ext.id_next_call_present;
2133 e_callerinfo.ntype = e_ext.id_next_call_type;
2134 e_ext.id_next_call_present = -1;
2135 /* extension is written */
2136 write_extension(&e_ext, e_ext.number);
2139 SCPY(e_callerinfo.id, e_ext.callerid);
2140 e_callerinfo.present = e_ext.callerid_present;
2141 e_callerinfo.ntype = e_ext.callerid_type;
2144 e_connectedmode = 1; /* dtmf-hangup & disconnect prevention */
2147 /* check if caller id is NOT authenticated */
2148 if (!parse_callbackauth(e_ext.number, &e_callbackinfo))
2150 /* make call state to enter password */
2151 new_state(EPOINT_STATE_IN_OVERLAP);
2152 e_action = &action_password_write;
2153 e_match_timeout = 0;
2154 e_match_to_action = NULL;
2155 e_dialinginfo.id[0] = '\0';
2156 e_extdialing = strchr(e_dialinginfo.id, '\0');
2157 e_password_timeout = now+20;
2161 /* incoming call (callback) */
2162 e_ruleset = ruleset_main;
2164 e_rule = e_ruleset->rule_first;
2166 e_extdialing = e_dialinginfo.id;
2167 if (e_dialinginfo.id[0])
2169 set_tone(portlist, "dialing");
2173 set_tone(portlist, "dialpbx");
2176 } else /* testcall */
2178 set_tone(portlist, "hold");
2181 /* start recording if enabled, not when answering machine answers */
2182 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))
2184 /* check if we are a terminal */
2185 if (e_ext.number[0] == '\0')
2186 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
2189 port = find_port_id(portlist->port_id);
2191 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
2196 /* port MESSAGE_DISCONNECT MESSAGE_RELEASE */
2197 void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
2199 struct message *message;
2201 unsigned long port_id = portlist->port_id;
2205 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2207 /* signal to call tool */
2208 admin_call_response(e_adminid, (message_type==MESSAGE_DISCONNECT)?ADMIN_CALL_DISCONNECT:ADMIN_CALL_RELEASE, "", param->disconnectinfo.cause, param->disconnectinfo.location, 0);
2210 //#warning does this work? only disconnect when incoming port hat not already disconnected yet?
2211 if (e_state==EPOINT_STATE_IN_DISCONNECT && message_type!=MESSAGE_RELEASE)// || e_state==EPOINT_STATE_OUT_DISCONNECT || e_state==EPOINT_STATE_IDLE)
2213 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are already disconnected.\n", ea_endpoint->ep_serial);
2218 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);
2219 collect_cause(&e_multipoint_cause, &e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location);
2220 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new multipoint cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location);
2222 /* check if we have more than one portlist relation and we just ignore the disconnect */
2223 if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist->next)
2225 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the disconnect was from a multipoint call. we just release that relation.\n", ea_endpoint->ep_serial);
2226 portlist = ea_endpoint->ep_portlist;
2229 if (portlist->port_id == port_id)
2231 portlist = portlist->next;
2234 FATAL("EPOINT(%d) no portlist related to the calling port.\n", ea_endpoint->ep_serial);
2235 if (message_type != MESSAGE_RELEASE)
2237 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2238 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2239 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2240 message_put(message);
2241 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2243 ea_endpoint->free_portlist(portlist);
2244 return; /* one relation removed */
2246 if (e_state == EPOINT_STATE_CONNECT)
2248 /* use cause from port after connect */
2249 cause = param->disconnectinfo.cause;
2250 location = param->disconnectinfo.location;
2253 /* use multipoint cause if no connect yet */
2254 if (e_multipoint_cause)
2256 cause = e_multipoint_cause;
2257 location = e_multipoint_location;
2260 cause = CAUSE_NOUSER;
2261 location = LOCATION_PRIVATE_LOCAL;
2265 e_cfnr_call = e_cfnr_release = 0;
2267 /* process hangup */
2268 process_hangup(e_join_cause, e_join_location);
2269 e_multipoint_cause = 0;
2270 e_multipoint_location = 0;
2272 if (message_type == MESSAGE_DISCONNECT)
2274 /* tone to disconnected end */
2275 SPRINT(buffer, "cause_%02x", cause);
2276 if (ea_endpoint->ep_portlist)
2277 set_tone(ea_endpoint->ep_portlist, buffer);
2279 new_state(EPOINT_STATE_IN_DISCONNECT);
2282 if (ea_endpoint->ep_join_id)
2284 int haspatterns = 0;
2285 /* check if pattern is available */
2286 if (ea_endpoint->ep_portlist)
2287 if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->early_b)
2288 if (joinpbx_countrelations(ea_endpoint->ep_join_id)==2 // we must count relations, in order not to disturb the conference ; NOTE: asterisk always counts two, since it is a point to point call
2289 && message_type != MESSAGE_RELEASE) // if we release, we are done
2293 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has patterns.\n", ea_endpoint->ep_serial);
2294 /* indicate patterns */
2295 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2296 message_put(message);
2297 /* connect audio, if not already */
2298 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2299 message->param.audiopath = CHANNEL_STATE_CONNECT;
2300 message_put(message);
2301 /* send disconnect */
2302 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2303 memcpy(&message->param, param, sizeof(union parameter));
2304 message_put(message);
2305 /* disable encryption if disconnected */
2306 //PERROR("REMOVE ME: state =%d, %d\n", e_crypt_state, e_crypt);
2308 cryptman_message(CI_DISCONNECT_IND, NULL, 0);
2312 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
2315 if (message_type == MESSAGE_RELEASE)
2316 ea_endpoint->free_portlist(portlist);
2317 release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, callcause, portcause */
2318 return; /* must exit here */
2321 /* port MESSAGE_TIMEOUT */
2322 void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type, union parameter *param)
2326 trace_header("TIMEOUT", DIRECTION_IN);
2327 message_type = MESSAGE_DISCONNECT;
2328 switch (param->state)
2330 case PORT_STATE_OUT_SETUP:
2331 case PORT_STATE_OUT_OVERLAP:
2332 add_trace("state", NULL, "outgoing setup/dialing");
2334 /* no user responding */
2335 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2336 return; /* must exit here */
2338 case PORT_STATE_IN_SETUP:
2339 case PORT_STATE_IN_OVERLAP:
2340 add_trace("state", NULL, "incoming setup/dialing");
2341 param->disconnectinfo.cause = CAUSE_INVALID; /* number incomplete */
2342 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2345 case PORT_STATE_OUT_PROCEEDING:
2346 add_trace("state", NULL, "outgoing proceeding");
2348 param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
2349 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2350 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2351 return; /* must exit here */
2353 case PORT_STATE_IN_PROCEEDING:
2354 add_trace("state", NULL, "incoming proceeding");
2355 param->disconnectinfo.cause = CAUSE_NOUSER;
2356 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL; /* no user responding */
2359 case PORT_STATE_OUT_ALERTING:
2360 add_trace("state", NULL, "outgoing alerting");
2362 param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
2363 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2364 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2365 return; /* must exit here */
2367 case PORT_STATE_CONNECT:
2368 add_trace("state", NULL, "connect");
2370 param->disconnectinfo.cause = CAUSE_NORMAL; /* normal */
2371 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2372 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2373 return; /* must exit here */
2375 case PORT_STATE_IN_ALERTING:
2376 add_trace("state", NULL, "incoming alerting");
2377 param->disconnectinfo.cause = CAUSE_NOANSWER;
2378 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2381 case PORT_STATE_IN_DISCONNECT:
2382 case PORT_STATE_OUT_DISCONNECT:
2383 add_trace("state", NULL, "disconnect");
2385 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
2386 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2387 return; /* must exit here */
2390 param->disconnectinfo.cause = 31; /* normal unspecified */
2391 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2394 /* release call, disconnect isdn */
2396 new_state(EPOINT_STATE_OUT_DISCONNECT);
2397 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2398 SCPY(e_tone, cause);
2401 set_tone(portlist, cause);
2402 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2403 portlist = portlist->next;
2405 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
2408 /* port MESSAGE_NOTIFY */
2409 void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, union parameter *param)
2411 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2413 struct message *message;
2417 /* signal to call tool */
2418 admin_call_response(e_adminid, ADMIN_CALL_NOTIFY, numberrize_callerinfo(param->notifyinfo.id,param->notifyinfo.ntype), 0, 0, param->notifyinfo.notify);
2419 if (param->notifyinfo.notify)
2421 e_rx_state = track_notify(e_rx_state, param->notifyinfo.notify);
2424 /* if we get notification from stack, local shows if we disabled/enabled audio stream */
2425 if (param->notifyinfo.local) switch(param->notifyinfo.notify)
2427 case INFO_NOTIFY_REMOTE_HOLD:
2428 case INFO_NOTIFY_USER_SUSPENDED:
2429 /* tell call about it */
2430 if (ea_endpoint->ep_join_id)
2432 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2433 message->param.audiopath = CHANNEL_STATE_HOLD;
2434 message_put(message);
2438 case INFO_NOTIFY_REMOTE_RETRIEVAL:
2439 case INFO_NOTIFY_USER_RESUMED:
2440 /* set volume of rx and tx */
2441 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
2442 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
2445 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2446 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2447 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
2448 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
2449 message_put(message);
2451 /* set current tone */
2453 set_tone(portlist, e_tone);
2454 /* tell call about it */
2455 if (ea_endpoint->ep_join_id)
2457 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2458 message->param.audiopath = CHANNEL_STATE_CONNECT;
2459 message_put(message);
2464 /* get name of notify */
2465 switch(param->notifyinfo.notify)
2471 logtext = "USER_SUSPENDED";
2474 logtext = "BEARER_SERVICE_CHANGED";
2477 logtext = "USER_RESUMED";
2480 logtext = "CONFERENCE_ESTABLISHED";
2483 logtext = "CONFERENCE_DISCONNECTED";
2486 logtext = "OTHER_PARTY_ADDED";
2489 logtext = "ISOLATED";
2492 logtext = "REATTACHED";
2495 logtext = "OTHER_PARTY_ISOLATED";
2498 logtext = "OTHER_PARTY_REATTACHED";
2501 logtext = "OTHER_PARTY_SPLIT";
2504 logtext = "OTHER_PARTY_DISCONNECTED";
2507 logtext = "CONFERENCE_FLOATING";
2510 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
2513 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
2516 logtext = "CALL_IS_A_WAITING_CALL";
2519 logtext = "DIVERSION_ACTIVATED";
2522 logtext = "RESERVED_CT_1";
2525 logtext = "RESERVED_CT_2";
2528 logtext = "REVERSE_CHARGING";
2531 logtext = "REMOTE_HOLD";
2534 logtext = "REMOTE_RETRIEVAL";
2537 logtext = "CALL_IS_DIVERTING";
2540 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
2545 /* notify call if available */
2546 if (ea_endpoint->ep_join_id)
2548 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOTIFY);
2549 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
2550 message_put(message);
2555 /* port MESSAGE_FACILITY */
2556 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
2558 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2560 struct message *message;
2562 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_FACILITY);
2563 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2564 message_put(message);
2567 /* port MESSAGE_SUSPEND */
2568 /* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
2569 void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
2571 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2573 /* epoint is now parked */
2574 ea_endpoint->ep_park = 1;
2575 memcpy(ea_endpoint->ep_park_callid, param->parkinfo.callid, sizeof(ea_endpoint->ep_park_callid));
2576 ea_endpoint->ep_park_len = (param->parkinfo.len>8)?8:param->parkinfo.len;
2578 /* remove port relation */
2579 ea_endpoint->free_portlist(portlist);
2582 /* port MESSAGE_RESUME */
2583 /* NOTE: before resume, the active-notification must be done in order to set call mixer */
2584 void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
2586 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2588 /* epoint is now resumed */
2589 ea_endpoint->ep_park = 0;
2594 /* port sends message to the endpoint
2596 void EndpointAppPBX::ea_message_port(unsigned long port_id, int message_type, union parameter *param)
2598 struct port_list *portlist;
2599 struct message *message;
2601 portlist = ea_endpoint->ep_portlist;
2604 if (port_id == portlist->port_id)
2606 portlist = portlist->next;
2610 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);
2614 // PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
2615 switch(message_type)
2617 case MESSAGE_DATA: /* data from port */
2618 /* check if there is a call */
2619 if (!ea_endpoint->ep_join_id)
2621 /* continue if only one portlist */
2622 if (ea_endpoint->ep_portlist->next != NULL)
2624 /* forward message */
2625 message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2628 case MESSAGE_TONE_EOF: /* tone is end of file */
2629 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
2632 if (e_action->index == ACTION_VBOX_PLAY)
2636 if (e_action->index == ACTION_EFI)
2643 case MESSAGE_TONE_COUNTER: /* counter info received */
2644 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);
2646 if (e_action->index == ACTION_VBOX_PLAY)
2648 e_vbox_counter = param->counter.current;
2649 if (param->counter.max >= 0)
2650 e_vbox_counter_max = param->counter.max;
2654 /* PORT sends SETUP message */
2656 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call from callerid=%s, dialing=%s\n", ea_endpoint->ep_serial, param->setup.callerinfo.id, param->setup.dialinginfo.id);
2657 if (e_state!=EPOINT_STATE_IDLE)
2659 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
2662 port_setup(portlist, message_type, param);
2665 /* PORT sends INFORMATION message */
2666 case MESSAGE_INFORMATION: /* additional digits received */
2667 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call dialing more=%s (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, param->information.id, e_ext.number, e_callerinfo.id);
2668 port_information(portlist, message_type, param);
2671 /* PORT sends FACILITY message */
2672 case MESSAGE_FACILITY:
2673 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2674 port_facility(portlist, message_type, param);
2677 /* PORT sends DTMF message */
2678 case MESSAGE_DTMF: /* dtmf digits received */
2679 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);
2680 port_dtmf(portlist, message_type, param);
2683 /* PORT sends CRYPT message */
2684 case MESSAGE_CRYPT: /* crypt response received */
2685 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) crypt response=%d\n", ea_endpoint->ep_serial, param->crypt.type);
2686 port_crypt(portlist, message_type, param);
2689 /* PORT sends MORE message */
2690 case MESSAGE_OVERLAP:
2691 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);
2692 if (e_state != EPOINT_STATE_OUT_SETUP)
2694 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);
2697 port_overlap(portlist, message_type, param);
2700 /* PORT sends PROCEEDING message */
2701 case MESSAGE_PROCEEDING: /* port is proceeding */
2702 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);
2703 if (e_state!=EPOINT_STATE_OUT_SETUP
2704 && e_state!=EPOINT_STATE_OUT_OVERLAP)
2706 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);
2709 port_proceeding(portlist, message_type, param);
2712 /* PORT sends ALERTING message */
2713 case MESSAGE_ALERTING:
2714 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);
2715 if (e_state!=EPOINT_STATE_OUT_SETUP
2716 && e_state!=EPOINT_STATE_OUT_OVERLAP
2717 && e_state!=EPOINT_STATE_OUT_PROCEEDING)
2719 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);
2722 port_alerting(portlist, message_type, param);
2725 /* PORT sends CONNECT message */
2726 case MESSAGE_CONNECT:
2727 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);
2728 if (e_state!=EPOINT_STATE_OUT_SETUP
2729 && e_state!=EPOINT_STATE_OUT_OVERLAP
2730 && e_state!=EPOINT_STATE_OUT_PROCEEDING
2731 && e_state!=EPOINT_STATE_OUT_ALERTING)
2733 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
2736 port_connect(portlist, message_type, param);
2739 /* PORT sends DISCONNECT message */
2740 case MESSAGE_DISCONNECT: /* port is disconnected */
2741 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);
2742 port_disconnect_release(portlist, message_type, param);
2745 /* PORT sends a RELEASE message */
2746 case MESSAGE_RELEASE: /* port releases */
2747 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);
2748 /* portlist is release at port_disconnect_release, thanx Paul */
2749 port_disconnect_release(portlist, message_type, param);
2752 /* PORT sends a TIMEOUT message */
2753 case MESSAGE_TIMEOUT:
2754 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);
2755 port_timeout(portlist, message_type, param);
2756 break; /* release */
2758 /* PORT sends a NOTIFY message */
2759 case MESSAGE_NOTIFY:
2760 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);
2761 port_notify(portlist, message_type, param);
2764 /* PORT sends a SUSPEND message */
2765 case MESSAGE_SUSPEND:
2766 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);
2767 port_suspend(portlist, message_type, param);
2768 break; /* suspend */
2770 /* PORT sends a RESUME message */
2771 case MESSAGE_RESUME:
2772 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);
2773 port_resume(portlist, message_type, param);
2777 /* port assigns bchannel */
2778 case MESSAGE_BCHANNEL: /* bchannel assignment messafe */
2779 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received bchannel message %d from port.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->bchannel.type);
2780 /* only one port is expected to be connected to bchannel */
2781 message = message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2782 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_IN);
2788 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);
2791 /* Note: this endpoint may be destroyed, so we MUST return */
2795 /* messages from join
2797 /* join MESSAGE_CRYPT */
2798 void EndpointAppPBX::join_crypt(struct port_list *portlist, int message_type, union parameter *param)
2800 switch(param->crypt.type)
2802 /* message from remote port to "crypt manager" */
2803 case CU_ACTK_REQ: /* activate key-exchange */
2804 case CU_ACTS_REQ: /* activate shared key */
2805 case CU_DACT_REQ: /* deactivate */
2806 case CU_INFO_REQ: /* request last info message */
2807 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2810 /* message from "crypt manager" to user */
2811 case CU_ACTK_CONF: /* key-echange done */
2812 case CU_ACTS_CONF: /* shared key done */
2813 case CU_DACT_CONF: /* deactivated */
2814 case CU_DACT_IND: /* deactivated */
2815 case CU_ERROR_IND: /* receive error message */
2816 case CU_INFO_IND: /* receive info message */
2817 case CU_INFO_CONF: /* receive info message */
2818 encrypt_result(param->crypt.type, (char *)param->crypt.data);
2822 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);
2826 /* join MESSAGE_INFORMATION */
2827 void EndpointAppPBX::join_information(struct port_list *portlist, int message_type, union parameter *param)
2829 struct message *message;
2835 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2836 memcpy(&message->param.information, ¶m->information, sizeof(struct dialing_info));
2837 message_put(message);
2838 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2839 portlist = portlist->next;
2843 /* join MESSAGE_FACILITY */
2844 void EndpointAppPBX::join_facility(struct port_list *portlist, int message_type, union parameter *param)
2846 struct message *message;
2848 if (!e_ext.facility && e_ext.number[0])
2855 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_FACILITY);
2856 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2857 message_put(message);
2858 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2859 portlist = portlist->next;
2863 /* join MESSAGE_MORE */
2864 void EndpointAppPBX::join_overlap(struct port_list *portlist, int message_type, union parameter *param)
2866 struct message *message;
2868 new_state(EPOINT_STATE_IN_OVERLAP);
2871 if (e_join_pattern && e_ext.own_setup)
2873 /* disconnect audio */
2874 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2875 message->param.audiopath = CHANNEL_STATE_HOLD;
2876 message_put(message);
2878 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
2880 if (e_dialinginfo.id[0])
2881 set_tone(portlist, "dialing");
2883 set_tone(portlist, "dialtone");
2886 if (e_ext.number[0])
2887 set_tone(portlist, "dialpbx");
2889 set_tone(portlist, "dialtone");
2892 /* join MESSAGE_PROCEEDING */
2893 void EndpointAppPBX::join_proceeding(struct port_list *portlist, int message_type, union parameter *param)
2895 struct message *message;
2897 new_state(EPOINT_STATE_IN_PROCEEDING);
2899 /* own proceeding tone */
2902 /* connect / disconnect audio */
2903 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2904 if (e_ext.own_proceeding)
2905 message->param.audiopath = CHANNEL_STATE_HOLD;
2907 message->param.audiopath = CHANNEL_STATE_CONNECT;
2908 message_put(message);
2910 // UCPY(e_join_tone, "proceeding");
2913 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
2914 message_put(message);
2915 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2917 set_tone(portlist, "proceeding");
2920 /* join MESSAGE_ALERTING */
2921 void EndpointAppPBX::join_alerting(struct port_list *portlist, int message_type, union parameter *param)
2923 struct message *message;
2925 new_state(EPOINT_STATE_IN_ALERTING);
2927 /* own alerting tone */
2930 /* connect / disconnect audio */
2931 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2932 if (e_ext.own_alerting)
2933 message->param.audiopath = CHANNEL_STATE_HOLD;
2935 message->param.audiopath = CHANNEL_STATE_CONNECT;
2936 message_put(message);
2940 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
2941 message_put(message);
2942 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2944 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
2946 set_tone(portlist, "ringing");
2949 if (e_ext.number[0])
2950 set_tone(portlist, "ringpbx");
2952 set_tone(portlist, "ringing");
2955 /* join MESSAGE_CONNECT */
2956 void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type, union parameter *param)
2958 struct message *message;
2960 new_state(EPOINT_STATE_CONNECT);
2961 // UCPY(e_join_tone, "");
2962 if (e_ext.number[0])
2963 e_dtmf = 1; /* allow dtmf */
2965 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_callerinfo));
2968 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
2969 memcpy(&message->param, param, sizeof(union parameter));
2971 /* screen clip if prefix is required */
2972 if (e_ext.number[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0])
2974 SCPY(message->param.connectinfo.id, e_ext.clip_prefix);
2975 SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype));
2976 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2979 /* use internal caller id */
2980 if (e_ext.number[0] && e_connectinfo.extension[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
2982 SCPY(message->param.connectinfo.id, e_connectinfo.extension);
2983 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2986 /* handle restricted caller ids */
2987 apply_callerid_restriction(&e_ext, message->param.connectinfo.id, &message->param.connectinfo.ntype, &message->param.connectinfo.present, &message->param.connectinfo.screen, message->param.connectinfo.extension, message->param.connectinfo.name);
2988 /* display callerid if desired for extension */
2989 SCPY(message->param.connectinfo.display, apply_callerid_display(message->param.connectinfo.id, message->param.connectinfo.itype, message->param.connectinfo.ntype, message->param.connectinfo.present, message->param.connectinfo.screen, message->param.connectinfo.extension, message->param.connectinfo.name));
2991 /* use conp, if enabld */
2992 // if (!e_ext.centrex)
2993 // message->param.connectinfo.name[0] = '\0';
2996 message_put(message);
2997 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2999 set_tone(portlist, NULL);
3001 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3002 message->param.audiopath = CHANNEL_STATE_CONNECT;
3003 message_put(message);
3007 /* join MESSAGE_DISCONNECT MESSAGE_RELEASE */
3008 void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *param)
3011 struct message *message;
3012 struct port_list *portlist = NULL;
3015 /* be sure that we are active */
3017 e_tx_state = NOTIFY_STATE_ACTIVE;
3019 /* we are powerdialing, if e_powerdialing is set and limit is not exceeded if given */
3020 if (e_powerdialing && ((e_powercount+1)<e_powerlimit || e_powerlimit<1))
3022 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
3024 /* set time for power dialing */
3025 e_powerdialing = now_d + e_powerdelay; /* set redial in the future */
3028 /* set redial tone */
3029 if (ea_endpoint->ep_portlist)
3033 set_tone(ea_endpoint->ep_portlist, "redial");
3034 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);
3035 /* send proceeding when powerdialing and still setup (avoid dialing timeout) */
3036 if (e_state==EPOINT_STATE_IN_OVERLAP)
3038 new_state(EPOINT_STATE_IN_PROCEEDING);
3039 if (ea_endpoint->ep_portlist)
3041 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3042 message_put(message);
3043 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3045 /* caused the error, that the first knock sound was not there */
3046 /* set_tone(portlist, "proceeding"); */
3048 /* send display of powerdialing */
3049 if (e_ext.display_dialing)
3051 portlist = ea_endpoint->ep_portlist;
3054 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3056 SPRINT(message->param.notifyinfo.display, "Retry %d of %d", e_powercount, e_powerlimit);
3058 SPRINT(message->param.notifyinfo.display, "Retry %d", e_powercount);
3059 message_put(message);
3060 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3061 portlist = portlist->next;
3070 if ((e_state!=EPOINT_STATE_CONNECT
3071 && e_state!=EPOINT_STATE_OUT_DISCONNECT
3072 && e_state!=EPOINT_STATE_IN_OVERLAP
3073 && e_state!=EPOINT_STATE_IN_PROCEEDING
3074 && e_state!=EPOINT_STATE_IN_ALERTING)
3075 || !ea_endpoint->ep_portlist) /* or no port */
3077 process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
3078 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause); /* RELEASE_TYPE, join, port */
3079 return; /* must exit here */
3084 e_join_cause = param->disconnectinfo.cause;
3085 e_join_location = param->disconnectinfo.location;
3088 /* on release we need the audio again! */
3089 if (message_type == MESSAGE_RELEASE)
3092 ea_endpoint->ep_join_id = 0;
3094 /* disconnect and select tone */
3095 new_state(EPOINT_STATE_OUT_DISCONNECT);
3096 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
3097 /* if own_cause, we must release the join */
3098 if (e_ext.own_cause /* own cause */
3099 || !e_join_pattern) /* no patterns */
3101 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have own cause or we have no patterns. (own_cause=%d pattern=%d)\n", ea_endpoint->ep_serial, e_ext.own_cause, e_join_pattern);
3102 if (message_type != MESSAGE_RELEASE)
3103 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
3105 } else /* else we enable audio */