1 /*****************************************************************************\
3 ** Linux Call Router **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
8 ** The EndpointAppPBX implements PBX4Linux **
10 \*****************************************************************************/
15 class EndpointAppPBX *apppbx_first = NULL;
18 * EndpointAppPBX constructor
20 EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint, int origin) : EndpointApp(epoint, origin)
22 class EndpointAppPBX **apppointer;
24 /* add application to chain */
26 apppointer = &apppbx_first;
28 apppointer = &((*apppointer)->next);
32 memset(&e_ext, 0, sizeof(struct extension));
33 // *************** NOTE: also change value in read_extension() **************
34 e_ext.rights = 4; /* international */
35 e_ext.rx_gain = e_ext.tx_gain = 0;
36 e_state = EPOINT_STATE_IDLE;
37 e_ext.number[0] = '\0';
38 e_extension_interface[0] = '\0';
39 memset(&e_callerinfo, 0, sizeof(struct caller_info));
40 memset(&e_dialinginfo, 0, sizeof(struct dialing_info));
41 memset(&e_connectinfo, 0, sizeof(struct connect_info));
42 memset(&e_redirinfo, 0, sizeof(struct redir_info));
43 memset(&e_capainfo, 0, sizeof(struct capa_info));
46 e_ruleset = ruleset_main;
48 e_rule = e_ruleset->rule_first;
53 e_match_to_action = NULL;
55 e_extdialing = e_dialinginfo.id;
59 // e_join_tone[0] = e_hold_tone[0] = '\0';
60 e_join_pattern /*= e_hold_pattern*/ = 0;
63 e_adminid = 0; // will be set, if call was initiated via admin socket
68 e_cbdialing[0] = '\0';
71 memset(&e_callbackinfo, 0, sizeof(struct caller_info));
78 e_password_timeout = 0;
79 e_multipoint_cause = 0;
80 e_multipoint_location = 0;
81 e_dialing_queue[0] = '\0';
83 e_crypt_state = CM_ST_NULL;
84 e_crypt_keyengine_busy = 0;
85 e_crypt_info[0] = '\0';
88 e_tx_state = NOTIFY_STATE_ACTIVE;
89 e_rx_state = NOTIFY_STATE_ACTIVE;
90 e_join_cause = e_join_location = 0;
91 /*********************************
92 *********************************
93 ********* ATTENTION *************
94 *********************************
95 *********************************/
96 /* if you add new values, that must be initialized, also check if they must
97 * be initialized when doing callback
103 * EpointAppPBX destructor
105 EndpointAppPBX::~EndpointAppPBX(void)
107 class EndpointAppPBX *temp, **tempp;
111 tempp = &apppbx_first;
121 FATAL("Endpoint not in endpoint's list.\n");
128 * trace header for application
130 void EndpointAppPBX::trace_header(char *name, int direction)
134 char msgtext[sizeof(_trace.name)];
138 /* init trace with given values */
141 numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype, options.national, options.international),
145 ea_endpoint->ep_serial,
152 /* set new endpoint state
154 void EndpointAppPBX::new_state(int state)
157 if (e_state != state)
159 trace_header("NEW STATE", DIRECTION_NONE);
160 add_trace("state", "old", "%s", state_name[e_state]);
161 add_trace("state", "new", "%s", state_name[state]);
169 /* release join and port (as specified)
171 void EndpointAppPBX::release(int release, int joinlocation, int joincause, int portlocation, int portcause)
173 struct port_list *portlist;
174 struct lcr_msg *message;
177 /* message to test call */
178 admin_call_response(e_adminid, ADMIN_CALL_RELEASE, "", joincause, joinlocation, 0);
180 /* if a release is pending */
181 if (release==RELEASE_JOIN || release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY)
183 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): do pending release (joincause %d location %d)\n", ea_endpoint->ep_serial, joincause, joinlocation);
184 if (ea_endpoint->ep_join_id)
186 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_RELEASE);
187 message->param.disconnectinfo.cause = joincause;
188 message->param.disconnectinfo.location = joinlocation;
189 message_put(message);
190 ea_endpoint->ep_join_id = 0;
194 if (release != RELEASE_PORT_JOINONLY)
197 join_release(e_hold_id, ea_endpoint->ep_serial, 1, joinlocation, joincause);
202 if (release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY)
204 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release (portcause %d portlocation)\n", ea_endpoint->ep_serial, portcause, portlocation);
205 while((portlist = ea_endpoint->ep_portlist))
207 if (portlist->port_id)
209 SPRINT(cause, "cause_%02x", portcause);
210 set_tone(portlist, cause);
211 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
212 message->param.disconnectinfo.cause = portcause;
213 message->param.disconnectinfo.location = portlocation;
214 message_put(message);
215 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
217 ea_endpoint->free_portlist(portlist);
220 /* if callback is enabled, call back with the given caller id */
223 /* reset some stuff */
224 new_state(EPOINT_STATE_IDLE);
225 memset(&e_connectinfo, 0, sizeof(struct connect_info));
226 memset(&e_redirinfo, 0, sizeof(struct redir_info));
227 e_start = e_stop = 0;
228 e_ruleset = ruleset_main;
230 e_rule = e_ruleset->rule_first;
232 e_action_timeout = 0;
234 e_match_to_action = NULL;
236 e_extdialing = e_dialinginfo.id;
243 e_multipoint_cause = 0;
244 e_multipoint_location = 0;
245 e_dialing_queue[0] = '\0';
247 e_crypt_state = CM_ST_NULL;
248 e_crypt_keyengine_busy = 0;
249 e_crypt_info[0] = '\0';
253 e_tx_state = NOTIFY_STATE_ACTIVE;
254 e_rx_state = NOTIFY_STATE_ACTIVE;
255 e_join_cause = e_join_location = 0;
257 /* the caller info of the callback user */
258 memcpy(&e_callbackinfo, &e_callerinfo, sizeof(e_callbackinfo));
259 memset(&e_dialinginfo, 0, sizeof(e_dialinginfo));
260 /* create dialing by callerinfo */
261 if (e_ext.number[0] && e_extension_interface[0])
263 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to internal: %s interface %s\n", ea_endpoint->ep_serial, e_ext.number, e_extension_interface);
264 /* create callback to the current terminal */
265 SCPY(e_dialinginfo.id, e_ext.number);
266 SCPY(e_dialinginfo.interfaces, e_extension_interface);
267 e_dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
268 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
273 SCPY(e_dialinginfo.id, e_cbto);
276 /* numberrize caller id and use it to dial to the callback */
277 SCPY(e_dialinginfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype, options.national, options.international));
279 e_dialinginfo.itype = INFO_ITYPE_ISDN;
280 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
281 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to external: %s\n", ea_endpoint->ep_serial, e_dialinginfo.id);
286 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release of epoint itself.\n", ea_endpoint->ep_serial);
287 ea_endpoint->ep_use--; /* when e_lock is 0, the endpoint will be deleted */
293 /* cancel callerid if restricted, unless anon-ignore is enabled at extension or port is of type external (so called police gets caller id :)*/
294 void apply_callerid_restriction(struct extension *ext, char *id, int *ntype, int *present, int *screen, char *extension, char *name)
296 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");
298 /* caller id is not restricted, so we do nothing */
299 if (*present != INFO_PRESENT_RESTRICTED)
302 /* only extensions are restricted */
306 /* if we enabled anonymouse ignore */
307 if (ext->anon_ignore)
310 /* else we remove the caller id */
314 *ntype = INFO_NTYPE_UNKNOWN;
316 // *screen = INFO_SCREEN_USER;
317 // maybe we should not make voip address anonymous
320 // maybe it's no fraud to present extension id
322 // extension[0] = '\0';
327 /* used display message to display callerid as available */
328 char *EndpointAppPBX::apply_callerid_display(char *id, int itype, int ntype, int present, int screen, char *extension, char *name)
330 static char display[81];
333 char *cid = numberrize_callerinfo(id, ntype, options.national, options.international);
335 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");
344 /* NOTE: is caller is is not available for this extesion, it has been removed by apply_callerid_restriction already */
346 /* internal extension's caller id */
347 if (extension[0] && e_ext.display_int)
350 SCAT(display, extension);
353 if (itype == INFO_ITYPE_VBOX)
354 SCAT(display, "(vbox)");
356 SCAT(display, "(int)");
359 /* external caller id */
360 if (!extension[0] && e_ext.display_ext)
366 if (present == INFO_PRESENT_RESTRICTED)
367 SCAT(display, "anonymous");
369 SCAT(display, "unknown");
376 /* display if callerid is anonymouse but available due anon-ignore */
377 if (e_ext.display_anon && present==INFO_PRESENT_RESTRICTED)
380 SCAT(display, "unknown");
383 SCAT(display, " anon");
386 /* display if callerid is anonymouse but available due anon-ignore */
387 if (e_ext.display_fake && screen==INFO_SCREEN_USER && present!=INFO_PRESENT_NULL)
393 if (present == INFO_PRESENT_RESTRICTED)
394 SCAT(display, "anonymous");
396 SCAT(display, "unknown");
401 SCAT(display, " fake");
405 if (name[0] && e_ext.display_name)
407 if (!display[0] && cid[0])
418 * uses the current state to notify activity
420 void EndpointAppPBX::notify_active(void)
422 struct port_list *portlist = ea_endpoint->ep_portlist;
423 struct lcr_msg *message;
428 case NOTIFY_STATE_ACTIVE:
429 /* we are already active, so we don't do anything */
432 case NOTIFY_STATE_SUSPEND:
433 notify = INFO_NOTIFY_USER_RESUMED;
436 set_tone(portlist, NULL);
437 portlist = portlist->next;
439 portlist = ea_endpoint->ep_portlist;
442 case NOTIFY_STATE_HOLD:
443 notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
446 set_tone(portlist, NULL);
447 portlist = portlist->next;
449 portlist = ea_endpoint->ep_portlist;
452 case NOTIFY_STATE_CONFERENCE:
453 notify = INFO_NOTIFY_CONFERENCE_DISCONNECTED;
456 set_tone(portlist, NULL);
457 portlist = portlist->next;
459 portlist = ea_endpoint->ep_portlist;
463 PERROR("unknown e_tx_state = %d\n", e_tx_state);
469 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
470 message->param.notifyinfo.notify = notify;
471 message_put(message);
472 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
473 portlist = portlist->next;
479 * keypad functions during call. one example to use this is to put a call on hold or start a conference
481 void EndpointAppPBX::keypad_function(char digit)
484 /* we must be in a call, in order to send messages to the call */
485 if (e_ext.number[0] == '\0')
487 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) IGNORING keypad received not from extension.\n", ea_endpoint->ep_serial);
493 /* join conference */
495 if (ea_endpoint->ep_join_id == 0)
497 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad received during connect but not during a call.\n", ea_endpoint->ep_serial);
500 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join call with call on hold\n", ea_endpoint->ep_serial);
506 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) shared key encryption selected.\n", ea_endpoint->ep_serial);
510 /* crypt key-exchange */
512 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) key exchange encryption selected.\n", ea_endpoint->ep_serial);
518 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) encryption off selected.\n", ea_endpoint->ep_serial);
523 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) unsupported keypad digit '%c'.\n", ea_endpoint->ep_serial, digit);
528 /* set tone pattern for port */
529 void EndpointAppPBX::set_tone(struct port_list *portlist, char *tone)
531 struct lcr_msg *message;
536 /* store for suspended processes */
540 if (e_join_pattern /* pattern are provided */
541 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_SETUP)
542 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_OVERLAP)
543 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_IN_PROCEEDING)
544 && !(e_ext.own_alerting && e_state == EPOINT_STATE_IN_ALERTING)
545 && !(e_ext.own_cause && e_state == EPOINT_STATE_IN_DISCONNECT)
546 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_SETUP)
547 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_OVERLAP)
548 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_OUT_PROCEEDING)
549 && !(e_ext.own_alerting && e_state == EPOINT_STATE_OUT_ALERTING)
550 && !(e_ext.own_cause && e_state == EPOINT_STATE_OUT_DISCONNECT)
551 && tone[0] && !!strncmp(tone,"crypt_*",6))
553 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) tone not provided since patterns are available\n", ea_endpoint->ep_serial);
559 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_TONE);
560 SCPY(message->param.tone.dir, e_ext.tones_dir[0]?e_ext.tones_dir:options.tones_dir);
561 SCPY(message->param.tone.name, tone);
562 message_put(message);
563 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
566 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port to notify tone.\n", ea_endpoint->ep_serial);
573 * hunts an mISDNport that is available for an outgoing call
574 * if no ifname was given, any interface that is not an extension
577 struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel)
579 struct interface *interface;
580 struct interface_port *ifport, *ifport_start;
581 struct select_channel *selchannel;
582 struct mISDNport *mISDNport;
585 interface = interface_first;
587 /* first find the given interface or, if not given, one with no extension */
592 /* check for given interface */
595 if (!strcasecmp(interface->name, ifname))
597 /* found explicit interface */
598 trace_header("CHANNEL SELECTION (found interface)", DIRECTION_NONE);
599 add_trace("interface", NULL, "%s", ifname);
606 if (!interface->extension)
608 /* found non extension */
609 trace_header("CHANNEL SELECTION (found non extension interface)", DIRECTION_NONE);
610 add_trace("interface", NULL, "%s", interface->name);
616 interface = interface->next;
620 /* see if interface has ports */
621 if (!interface->ifport)
624 trace_header("CHANNEL SELECTION (interface has no active ports, skipping)", DIRECTION_NONE);
625 add_trace("interface", NULL, "%s", interface->name);
627 interface = interface->next;
631 /* select port by algorithm */
632 ifport_start = interface->ifport;
634 if (interface->hunt == HUNT_ROUNDROBIN)
636 while(ifport_start->next && index<interface->hunt_next)
638 ifport_start = ifport_start->next;
641 trace_header("CHANNEL SELECTION (starting round-robin)", DIRECTION_NONE);
642 add_trace("port", NULL, "%d", ifport_start->portnum);
643 add_trace("position", NULL, "%d", index);
648 ifport = ifport_start;
651 /* see if port is available */
652 if (!ifport->mISDNport)
654 trace_header("CHANNEL SELECTION (port not available, skipping)", DIRECTION_NONE);
655 add_trace("port", NULL, "%d", ifport->portnum);
656 add_trace("position", NULL, "%d", index);
660 mISDNport = ifport->mISDNport;
662 /* see if port is administratively blocked */
665 trace_header("CHANNEL SELECTION (port blocked by admin, skipping)", DIRECTION_NONE);
666 add_trace("port", NULL, "%d", ifport->portnum);
667 add_trace("position", NULL, "%d", index);
672 /* see if link is up on PTP*/
673 if (mISDNport->l2hold && !mISDNport->l2link)
675 trace_header("CHANNEL SELECTION (port holds layer 2, but layer 2 is down, skipping)", DIRECTION_NONE);
676 add_trace("port", NULL, "%d", ifport->portnum);
677 add_trace("position", NULL, "%d", index);
682 /* check for channel form selection list */
684 selchannel = ifport->out_channel;
687 switch(selchannel->channel)
689 case CHANNEL_FREE: /* free channel */
690 if (mISDNport->b_reserved >= mISDNport->b_num)
691 break; /* all channel in use or reserverd */
694 while(i < mISDNport->b_num)
696 if (mISDNport->b_port[i] == NULL)
698 *channel = i+1+(i>=15);
699 trace_header("CHANNEL SELECTION (selecting free channel)", DIRECTION_NONE);
700 add_trace("port", NULL, "%d", ifport->portnum);
701 add_trace("position", NULL, "%d", index);
702 add_trace("channel", NULL, "%d", *channel);
710 trace_header("CHANNEL SELECTION (no channel is 'free')", DIRECTION_NONE);
711 add_trace("port", NULL, "%d", ifport->portnum);
712 add_trace("position", NULL, "%d", index);
716 case CHANNEL_ANY: /* don't ask for channel */
717 if (mISDNport->b_reserved >= mISDNport->b_num)
719 trace_header("CHANNEL SELECTION (cannot ask for 'any' channel, all reserved)", DIRECTION_NONE);
720 add_trace("port", NULL, "%d", ifport->portnum);
721 add_trace("position", NULL, "%d", index);
722 add_trace("total", NULL, "%d", mISDNport->b_num);
723 add_trace("reserved", NULL, "%d", mISDNport->b_reserved);
725 break; /* all channel in use or reserverd */
727 trace_header("CHANNEL SELECTION (using 'any' channel)", DIRECTION_NONE);
728 add_trace("port", NULL, "%d", ifport->portnum);
729 add_trace("position", NULL, "%d", index);
731 *channel = CHANNEL_ANY;
734 case CHANNEL_NO: /* call waiting */
735 trace_header("CHANNEL SELECTION (using 'no' channel, call-waiting)", DIRECTION_NONE);
736 add_trace("port", NULL, "%d", ifport->portnum);
737 add_trace("position", NULL, "%d", index);
739 *channel = CHANNEL_NO;
743 if (selchannel->channel<1 || selchannel->channel==16)
745 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
746 add_trace("port", NULL, "%d", ifport->portnum);
747 add_trace("position", NULL, "%d", index);
748 add_trace("channel", NULL, "%d", selchannel->channel);
750 break; /* invalid channels */
752 i = selchannel->channel-1-(selchannel->channel>=17);
753 if (i >= mISDNport->b_num)
755 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
756 add_trace("port", NULL, "%d", ifport->portnum);
757 add_trace("position", NULL, "%d", index);
758 add_trace("channel", NULL, "%d", selchannel->channel);
759 add_trace("channels", NULL, "%d", mISDNport->b_num);
761 break; /* channel not in port */
763 if (mISDNport->b_port[i] == NULL)
765 *channel = selchannel->channel;
766 trace_header("CHANNEL SELECTION (selecting given channel)", DIRECTION_NONE);
767 add_trace("port", NULL, "%d", ifport->portnum);
768 add_trace("position", NULL, "%d", index);
769 add_trace("channel", NULL, "%d", *channel);
776 break; /* found channel */
777 selchannel = selchannel->next;
780 /* if channel was found, return mISDNport and channel */
783 /* setting next port to start next time */
784 if (interface->hunt == HUNT_ROUNDROBIN)
789 interface->hunt_next = index;
795 trace_header("CHANNEL SELECTION (skipping, no channel found)", DIRECTION_NONE);
796 add_trace("port", NULL, "%d", ifport->portnum);
797 add_trace("position", NULL, "%d", index);
801 /* go next port, until all ports are checked */
803 ifport = ifport->next;
807 ifport = interface->ifport;
809 if (ifport != ifport_start)
812 return(NULL); /* no port found */
815 /* outgoing setup to port(s)
816 * ports will be created and a setup is sent if everything is ok. otherwhise
817 * the endpoint is destroyed.
819 void EndpointAppPBX::out_setup(void)
821 struct dialing_info dialinginfo;
823 // class pdss1 *pdss1;
824 struct port_list *portlist;
825 struct lcr_msg *message;
827 int cause = CAUSE_RESSOURCEUNAVAIL;
830 struct mISDNport *mISDNport;
833 class EndpointAppPBX *atemp;
834 // char allowed_ports[256];
836 char ifname[sizeof(e_ext.interfaces)],
838 struct port_settings port_settings;
842 /* create settings for creating port */
843 memset(&port_settings, 0, sizeof(port_settings));
845 SCPY(port_settings.tones_dir, e_ext.tones_dir);
847 SCPY(port_settings.tones_dir, options.tones_dir);
848 port_settings.no_seconds = e_ext.no_seconds;
850 /* 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 */
852 /* check what dialinginfo.itype we got */
853 switch(e_dialinginfo.itype)
855 /* *********************** call to extension or vbox */
856 case INFO_ITYPE_ISDN_EXTENSION:
857 /* check if we deny incoming calls when we use an extension */
858 if (e_ext.noknocking)
860 atemp = apppbx_first;
864 if (!strcmp(atemp->e_ext.number, e_ext.number))
870 PERROR("EPOINT(%d) noknocking and currently a call\n", ea_endpoint->ep_serial);
871 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYSPE_ join, port */
872 return; /* must exit here */
875 /* FALL THROUGH !!!! */
876 case INFO_ITYPE_VBOX:
877 /* get dialed extension's info */
878 // SCPY(exten, e_dialinginfo.id);
879 // if (strchr(exten, ','))
880 // *strchr(exten, ',') = '\0';
881 // if (!read_extension(&e_ext, exten))
882 if (!read_extension(&e_ext, e_dialinginfo.id))
884 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) extension %s not configured\n", ea_endpoint->ep_serial, e_dialinginfo.id);
885 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
886 return; /* must exit here */
889 if (e_dialinginfo.itype == INFO_ITYPE_VBOX)
891 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing directly to VBOX\n", ea_endpoint->ep_serial);
896 /* string from unconditional call forward (cfu) */
900 /* present to forwarded party */
901 if (e_ext.anon_ignore && e_callerinfo.id[0])
903 e_callerinfo.present = INFO_PRESENT_ALLOWED;
905 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
909 /* string from busy call forward (cfb) */
913 class EndpointAppPBX *checkapp = apppbx_first;
916 if (checkapp != this) /* any other endpoint except our own */
918 if (!strcmp(checkapp->e_ext.number, e_ext.number))
920 /* present to forwarded party */
921 if (e_ext.anon_ignore && e_callerinfo.id[0])
923 e_callerinfo.present = INFO_PRESENT_ALLOWED;
925 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
929 checkapp = checkapp->next;
933 /* string from no-response call forward (cfnr) */
937 /* when cfnr is done, out_setup() will setup the call */
940 /* present to forwarded party */
941 if (e_ext.anon_ignore && e_callerinfo.id[0])
943 e_callerinfo.present = INFO_PRESENT_ALLOWED;
947 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
949 e_cfnr_release = now + e_ext.cfnr_delay;
950 e_cfnr_call = now + e_ext.cfnr_delay + 1; /* call one second after release */
951 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);
955 /* call to all internal interfaces */
956 p = e_ext.interfaces;
957 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) generating multiple joins for extension %s to interfaces %s\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
961 while(*p!=',' && *p!='\0')
966 /* found interface */
967 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
968 /* hunt for mISDNport and create Port */
969 mISDNport = hunt_port(ifname, &channel);
972 trace_header("INTERFACE (not found or busy)", DIRECTION_NONE);
973 add_trace("interface", NULL, "%s", ifname);
977 /* creating INTERNAL port */
978 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
979 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force);
981 FATAL("No memory for DSS1 Port instance\n");
982 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
983 memset(&dialinginfo, 0, sizeof(dialinginfo));
984 SCPY(dialinginfo.id, e_dialinginfo.id);
985 dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
986 dialinginfo.ntype = e_dialinginfo.ntype;
987 /* create port_list relation */
988 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
991 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
993 goto check_anycall_intern;
996 if (e_callerinfo.id[0] && e_ext.display_name)
998 dirname = parse_directory(e_callerinfo.id, e_callerinfo.ntype);
1000 SCPY(e_callerinfo.name, dirname);
1002 // dss1 = (class Pdss1 *)port;
1004 //printf("INTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1005 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1006 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1007 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1008 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1009 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1010 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1011 //terminal if (e_dialinginfo.id)
1012 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1013 /* handle restricted caller ids */
1014 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);
1015 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);
1016 /* display callerid if desired for extension */
1017 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));
1018 //printf("\n\ndisplay = %s\n\n\n",message->param.setup.callerinfo.display);
1019 /* use cnip, if enabld */
1020 // if (!e_ext.centrex)
1021 // message->param.setup.callerinfo.name[0] = '\0';
1022 /* screen clip if prefix is required */
1023 if (message->param.setup.callerinfo.id[0] && e_ext.clip_prefix[0])
1025 SCPY(message->param.setup.callerinfo.id, e_ext.clip_prefix);
1026 SCAT(message->param.setup.callerinfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype, options.national, options.international));
1027 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1029 /* use internal caller id */
1030 if (e_callerinfo.extension[0] && (message->param.setup.callerinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
1032 SCPY(message->param.setup.callerinfo.id, e_callerinfo.extension);
1033 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1035 message_put(message);
1036 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1040 /* string from parallel call forward (cfp) */
1044 if (e_ext.anon_ignore && e_callerinfo.id[0])
1046 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1050 vbox_only: /* entry point for answering machine only */
1051 cfu_only: /* entry point for cfu */
1052 cfb_only: /* entry point for cfb */
1053 cfnr_only: /* entry point for cfnr */
1054 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call extension %s for external destiantion(s) '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
1059 /* only if vbox should be dialed, and terminal is given */
1060 if (!strcmp(p, "vbox") && e_ext.number[0])
1062 /* go to the end of p */
1065 /* answering vbox call */
1066 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) answering machine\n", ea_endpoint->ep_serial);
1068 if (!(port = new VBoxPort(PORT_TYPE_VBOX_OUT, &port_settings)))
1069 FATAL("No memory for VBOX Port instance\n");
1070 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocated port %s\n", ea_endpoint->ep_serial, port->p_name);
1071 UCPY(cfp, e_ext.number); /* cfp or any other direct forward/vbox */
1075 while(*p!=',' && *p!='\0')
1080 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cfp external %s\n", ea_endpoint->ep_serial, cfp);
1081 /* hunt for mISDNport and create Port */
1082 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1085 /* creating EXTERNAL port*/
1086 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1087 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)))
1088 FATAL("No memory for DSS1 Port instance\n");
1089 earlyb = mISDNport->earlyb;
1093 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1094 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1100 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port found or created, which is idle.\n", ea_endpoint->ep_serial);
1101 goto check_anycall_intern;
1103 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found or created port %s\n", ea_endpoint->ep_serial, port->p_name);
1104 memset(&dialinginfo, 0, sizeof(dialinginfo));
1105 SCPY(dialinginfo.id, cfp);
1106 dialinginfo.itype = INFO_ITYPE_ISDN;
1107 dialinginfo.ntype = e_dialinginfo.ntype;
1108 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
1111 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1113 goto check_anycall_intern;
1115 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1116 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1117 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1118 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1119 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1120 /* if clip is hidden */
1121 if (e_ext.clip==CLIP_HIDE && port->p_type!=PORT_TYPE_VBOX_OUT)
1123 SCPY(message->param.setup.callerinfo.id, e_ext.callerid);
1124 SCPY(message->param.setup.callerinfo.extension, e_ext.number);
1125 message->param.setup.callerinfo.ntype = e_ext.callerid_type;
1126 message->param.setup.callerinfo.present = e_ext.callerid_present;
1128 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1129 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1130 //terminal if (e_dialinginfo.id)
1131 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1132 /* handle restricted caller ids */
1133 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);
1134 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);
1135 /* display callerid if desired for extension */
1136 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));
1137 message_put(message);
1138 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1142 check_anycall_intern:
1143 /* now we have all ports created */
1146 trace_header("INTERFACE (no extension's interface)", DIRECTION_NONE);
1148 if (!ea_endpoint->ep_join_id)
1150 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1151 return; /* must exit here */
1155 /* *********************** external call */
1157 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id);
1158 /* call to extenal interfaces */
1159 p = e_dialinginfo.id;
1163 while(*p!=',' && *p!='\0')
1164 SCCAT(number, *p++);
1168 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");
1169 /* hunt for mISDNport and create Port */
1170 /* hunt for mISDNport and create Port */
1171 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1174 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1175 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1177 goto check_anycall_extern;
1179 /* creating EXTERNAL port*/
1180 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1181 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)))
1182 FATAL("No memory for DSS1 Port instance\n");
1183 earlyb = mISDNport->earlyb;
1184 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
1185 memset(&dialinginfo, 0, sizeof(dialinginfo));
1186 SCPY(dialinginfo.id, number);
1187 dialinginfo.itype = INFO_ITYPE_ISDN;
1188 dialinginfo.ntype = e_dialinginfo.ntype;
1189 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
1192 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1194 goto check_anycall_extern;
1196 // dss1 = (class Pdss1 *)port;
1197 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1198 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1199 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1200 SCPY(message->param.setup.dialinginfo.id, number);
1201 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1202 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1203 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1204 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1205 //terminal if (e_dialinginfo.id)
1206 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1207 /* handle restricted caller ids */
1208 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);
1209 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);
1210 /* display callerid if desired for extension */
1211 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));
1212 message_put(message);
1213 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1217 check_anycall_extern:
1218 /* now we have all ports created */
1221 trace_header("INTERFACE (no free ports found)", DIRECTION_NONE);
1223 if (!ea_endpoint->ep_join_id)
1225 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1226 return; /* must exit here */
1234 /* handler for endpoint
1238 int EndpointAppPBX::handler(void)
1240 if (e_crypt_state!=CM_ST_NULL)
1245 /* process answering machine (play) handling */
1248 if (e_action->index == ACTION_VBOX_PLAY)
1251 /* process action timeout */
1252 if (e_action_timeout)
1253 if (now_d >= e_action_timeout)
1255 if (e_state!=EPOINT_STATE_CONNECT)
1258 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current action timed out.\n", ea_endpoint->ep_serial);
1259 e_multipoint_cause = 0;
1260 e_multipoint_location = 0;
1261 new_state(EPOINT_STATE_IN_OVERLAP);
1264 return(1); /* we must exit, because our endpoint might be gone */
1266 e_action_timeout = 0;
1269 /* process action timeout */
1270 if (e_match_timeout)
1271 if (now_d >= e_match_timeout)
1274 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we got a match timeout.\n", ea_endpoint->ep_serial);
1276 return(1); /* we must exit, because our endpoint might be gone */
1281 /* process redialing (epoint redials to port) */
1284 if (now_d >= e_redial)
1287 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial.\n", ea_endpoint->ep_serial);
1289 new_state(EPOINT_STATE_OUT_SETUP);
1290 /* call special setup routine */
1297 /* process powerdialing (epoint redials to epoint) */
1298 if (e_powerdialing > 0)
1300 if (now_d >= e_powerdialing)
1302 e_powerdialing = -1; /* leave power dialing on */
1303 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial of powerdial.\n", ea_endpoint->ep_serial);
1306 e_ruleset = ruleset_main;
1308 e_rule = e_ruleset->rule_first;
1310 new_state(EPOINT_STATE_IN_OVERLAP);
1316 /* process call forward no response */
1319 struct port_list *portlist;
1320 struct lcr_msg *message;
1322 if (now >= e_cfnr_release)
1324 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-no-response time has expired, hanging up.\n", ea_endpoint->ep_serial);
1327 /* release all ports */
1328 while((portlist = ea_endpoint->ep_portlist))
1330 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1331 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
1332 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1333 message_put(message);
1334 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1335 ea_endpoint->free_portlist(portlist);
1338 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1339 message->param.audiopath = CHANNEL_STATE_HOLD;
1340 message_put(message);
1341 /* indicate no patterns */
1342 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1343 message_put(message);
1344 /* set setup state, since we have no response from the new join */
1345 new_state(EPOINT_STATE_OUT_SETUP);
1350 if (now >= e_cfnr_call)
1352 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-busy time has expired, calling the forwarded number: %s.\n", ea_endpoint->ep_serial, e_ext.cfnr);
1358 /* handle connection to user */
1359 if (e_state == EPOINT_STATE_IDLE)
1361 /* epoint is idle, check callback */
1363 if (now_d >= e_callback)
1365 e_callback = 0; /* done with callback */
1366 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting callback.\n", ea_endpoint->ep_serial);
1367 new_state(EPOINT_STATE_OUT_SETUP);
1373 /* check for password timeout */
1375 if (e_action->index==ACTION_PASSWORD || e_action->index==ACTION_PASSWORD_WRITE)
1377 struct port_list *portlist;
1379 if (now >= e_password_timeout)
1381 e_ruleset = ruleset_main;
1383 e_rule = e_ruleset->rule_first;
1385 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) password timeout %s\n", ea_endpoint->ep_serial, e_extdialing);
1386 trace_header("PASSWORD timeout", DIRECTION_NONE);
1388 e_connectedmode = 0;
1390 new_state(EPOINT_STATE_OUT_DISCONNECT);
1391 portlist = ea_endpoint->ep_portlist;
1394 message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
1395 set_tone(portlist, "cause_10");
1405 /* doing a hookflash */
1406 void EndpointAppPBX::hookflash(void)
1410 /* be sure that we are active */
1412 e_tx_state = NOTIFY_STATE_ACTIVE;
1414 trace_header("HOOKFLASH DTMF", DIRECTION_NONE);
1416 if (ea_endpoint->ep_use > 1)
1418 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot hooflash while child process is running.\n", ea_endpoint->ep_serial);
1421 /* dialtone after pressing the hash key */
1422 process_hangup(e_join_cause, e_join_location);
1423 e_multipoint_cause = 0;
1424 e_multipoint_location = 0;
1425 port = find_port_id(ea_endpoint->ep_portlist->port_id);
1428 port->set_echotest(0);
1430 if (ea_endpoint->ep_join_id)
1432 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1434 e_ruleset = ruleset_main;
1436 e_rule = e_ruleset->rule_first;
1438 new_state(EPOINT_STATE_IN_OVERLAP);
1439 e_connectedmode = 1;
1440 SCPY(e_dialinginfo.id, e_ext.prefix);
1441 e_extdialing = e_dialinginfo.id;
1443 if (e_dialinginfo.id[0])
1445 set_tone(ea_endpoint->ep_portlist, "dialing");
1449 set_tone(ea_endpoint->ep_portlist, "dialpbx");
1456 /* messages from port
1458 /* port MESSAGE_SETUP */
1459 void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, union parameter *param)
1461 struct lcr_msg *message;
1463 int writeext; /* flags need to write extension after modification */
1465 struct interface *interface;
1467 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1469 portlist->port_type = param->setup.port_type;
1470 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
1471 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
1472 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
1473 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
1474 e_dtmf = param->setup.dtmf;
1475 /* screen incoming caller id */
1476 interface = interface_first;
1479 if (!strcmp(e_callerinfo.interface, interface->name))
1483 interface = interface->next;
1486 do_screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface);
1488 /* process extension */
1489 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1491 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is extension\n", ea_endpoint->ep_serial);
1492 /* port makes call from extension */
1493 SCPY(e_callerinfo.extension, e_callerinfo.id);
1494 SCPY(e_ext.number, e_callerinfo.extension);
1495 SCPY(e_extension_interface, e_callerinfo.interface);
1498 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is external or voip\n", ea_endpoint->ep_serial);
1501 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1503 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1505 /* get extension's info about caller */
1506 if (!read_extension(&e_ext, e_ext.number))
1508 /* extension doesn't exist */
1509 trace_header("EXTENSION (not created)", DIRECTION_IN);
1510 add_trace("extension", NULL, "%s", e_ext.number);
1512 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
1513 new_state(EPOINT_STATE_OUT_DISCONNECT);
1514 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
1515 e_ext.number[0] = '\0'; /* no terminal */
1520 /* put prefix (next) in front of e_dialinginfo.id */
1523 SPRINT(buffer, "%s%s", e_ext.next, e_dialinginfo.id);
1524 SCPY(e_dialinginfo.id, buffer);
1525 e_ext.next[0] = '\0';
1527 } else if (e_ext.prefix[0])
1529 SPRINT(buffer, "%s%s", e_ext.prefix, e_dialinginfo.id);
1530 SCPY(e_dialinginfo.id, buffer);
1533 /* screen caller id by extension's config */
1534 e_callerinfo.screen = INFO_SCREEN_NETWORK;
1536 SCPY(e_callerinfo.name, e_ext.name);
1537 /* use caller id (or if exist: id_next_call) for this call */
1538 if (e_ext.id_next_call_present >= 0)
1540 SCPY(e_callerinfo.id, e_ext.id_next_call);
1541 /* if we restrict the pesentation */
1542 if (e_ext.id_next_call_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1543 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1544 else e_callerinfo.present = e_ext.id_next_call_present;
1545 e_callerinfo.ntype = e_ext.id_next_call_type;
1546 e_ext.id_next_call_present = -1;
1550 SCPY(e_callerinfo.id, e_ext.callerid);
1551 /* if we restrict the pesentation */
1552 if (e_ext.callerid_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1553 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1554 else e_callerinfo.present = e_ext.callerid_present;
1555 e_callerinfo.ntype = e_ext.callerid_type;
1558 /* extension is written */
1560 write_extension(&e_ext, e_ext.number);
1562 /* set volume of rx and tx */
1563 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1564 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
1566 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
1567 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
1568 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
1569 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
1570 message_put(message);
1573 /* start recording if enabled */
1574 if (e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO))
1576 /* check if we are a terminal */
1577 if (e_ext.number[0] == '\0')
1578 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
1581 port = find_port_id(portlist->port_id);
1583 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
1588 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from external port\n", ea_endpoint->ep_serial);
1589 /* no terminal identification */
1590 e_ext.number[0] = '\0';
1591 e_extension_interface[0] = '\0';
1592 memset(&e_ext, 0, sizeof(e_ext));
1593 e_ext.rights = 4; /* right to dial internat */
1597 e_ruleset = ruleset_main;
1599 e_rule = e_ruleset->rule_first;
1601 e_extdialing = e_dialinginfo.id;
1602 new_state(EPOINT_STATE_IN_SETUP);
1603 if (e_dialinginfo.id[0])
1605 set_tone(portlist, "dialing");
1608 if (e_ext.number[0])
1609 set_tone(portlist, "dialpbx");
1611 set_tone(portlist, "dialtone");
1614 if (e_state == EPOINT_STATE_IN_SETUP)
1616 /* request MORE info, if not already at higher state */
1617 new_state(EPOINT_STATE_IN_OVERLAP);
1618 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_OVERLAP);
1619 message_put(message);
1620 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1624 /* port MESSAGE_INFORMATION */
1625 void EndpointAppPBX::port_information(struct port_list *portlist, int message_type, union parameter *param)
1627 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1631 /* turn off dtmf detection, in case dtmf is sent with keypad information */
1634 trace_header("DTMF (disabling due to keypad)", DIRECTION_IN);
1639 /* if vbox_play is done, the information are just used as they come */
1641 if (e_action->index == ACTION_VBOX_PLAY)
1643 /* concat dialing string */
1644 SCAT(e_dialinginfo.id, param->information.id);
1649 /* keypad when disconnect but in connected mode */
1650 if (e_state==EPOINT_STATE_OUT_DISCONNECT && e_connectedmode)
1652 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received after disconnect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1653 /* processing keypad function */
1654 if (param->information.id[0] == '0')
1661 /* keypad when connected */
1662 if (e_state == EPOINT_STATE_CONNECT)
1666 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1667 /* processing keypad function */
1668 if (param->information.id[0] == '0')
1672 if (param->information.id[0])
1673 keypad_function(param->information.id[0]);
1676 if (e_ext.number[0])
1677 trace_header("KEYPAD (not enabled by extension's settings)", DIRECTION_IN);
1679 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1684 if (e_state != EPOINT_STATE_IN_OVERLAP)
1686 if (e_ext.number[0])
1687 trace_header("KEYPAD (ignored, not connected and not dialing)", DIRECTION_IN);
1689 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1693 if (!param->information.id[0])
1695 if (e_dialinginfo.id[0]=='\0' && !e_action)
1697 set_tone(portlist, "dialing");
1700 if (e_action->index==ACTION_OUTDIAL
1701 || e_action->index==ACTION_EXTERNAL)
1704 set_tone(portlist, "dialing");
1705 else if (!e_extdialing[0])
1706 set_tone(portlist, "dialing");
1708 /* concat dialing string */
1709 SCAT(e_dialinginfo.id, param->information.id);
1713 /* port MESSAGE_DTMF */
1714 void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
1716 /* only if dtmf detection is enabled */
1719 trace_header("DTMF (disabled)", DIRECTION_IN);
1723 trace_header("DTMF", DIRECTION_IN);
1724 add_trace("digit", NULL, "%c", param->dtmf);
1728 NOTE: vbox is now handled due to overlap state
1729 /* if vbox_play is done, the dtmf digits are just used as they come */
1731 if (e_action->index == ACTION_VBOX_PLAY)
1733 /* concat dialing string */
1734 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id))
1736 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1737 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1740 /* continue to process *X# sequences */
1744 /* check for *X# sequence */
1745 if (e_state == EPOINT_STATE_CONNECT)
1747 if (e_dtmf_time+3 < now)
1749 /* the last digit was too far in the past to be a sequence */
1750 if (param->dtmf == '*')
1751 /* only start is allowed in the sequence */
1757 /* we have a sequence of digits, see what we got */
1758 if (param->dtmf == '*')
1760 else if (param->dtmf>='0' && param->dtmf<='9')
1762 /* we need to have a star before we receive the digit of the sequence */
1763 if (e_dtmf_last == '*')
1764 e_dtmf_last = param->dtmf;
1765 } else if (param->dtmf == '#')
1768 if (e_dtmf_last>='0' && e_dtmf_last<='9')
1770 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf sequence *%c# detected.\n", ea_endpoint->ep_serial, e_dtmf_last);
1771 if (e_dtmf_last == '0')
1776 /* processing keypad function */
1778 keypad_function(e_dtmf_last);
1784 /* set last time of dtmf */
1789 /* check for ## hookflash during dialing */
1791 if (e_action->index==ACTION_PASSWORD
1792 || e_action->index==ACTION_PASSWORD_WRITE)
1794 if (param->dtmf=='#') /* current digit is '#' */
1796 if (e_state==EPOINT_STATE_IN_DISCONNECT
1797 || (e_state!=EPOINT_STATE_CONNECT && e_dtmf_time+3>=now && e_dtmf_last=='#')) /* when disconnected, just #. when dialing, ##. */
1814 /* dialing using dtmf digit */
1815 if (e_state==EPOINT_STATE_IN_OVERLAP)// && e_state==e_connectedmode)
1817 if (e_dialinginfo.id[0]=='\0' && !e_action)
1819 set_tone(portlist, "dialing");
1821 /* concat dialing string */
1822 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id))
1824 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1825 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1831 /* port MESSAGE_CRYPT */
1832 void EndpointAppPBX::port_crypt(struct port_list *portlist, int message_type, union parameter *param)
1834 /* send crypt response to cryptman */
1835 if (param->crypt.type == CR_MESSAGE_IND)
1836 cryptman_msg2man(param->crypt.data, param->crypt.len);
1838 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
1841 /* port MESSAGE_OVERLAP */
1842 void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, union parameter *param)
1844 struct lcr_msg *message;
1846 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1848 /* signal to call tool */
1849 admin_call_response(e_adminid, ADMIN_CALL_SETUP_ACK, "", 0, 0, 0);
1851 if (e_dialing_queue[0] && portlist)
1853 /* send what we have not dialed yet, because we had no setup complete */
1854 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing pending digits: '%s'\n", ea_endpoint->ep_serial, e_dialing_queue);
1855 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
1856 SCPY(message->param.information.id, e_dialing_queue);
1857 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
1858 message_put(message);
1859 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
1860 e_dialing_queue[0] = '\0';
1862 /* check if pattern is available */
1863 if (!ea_endpoint->ep_portlist->next && portlist->early_b) /* one port_list relation and tones available */
1865 /* indicate patterns */
1866 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1867 message_put(message);
1869 /* connect audio, if not already */
1870 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1871 message->param.audiopath = CHANNEL_STATE_CONNECT;
1872 message_put(message);
1875 /* indicate no patterns */
1876 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1877 message_put(message);
1879 /* disconnect audio, if not already */
1880 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1881 message->param.audiopath = CHANNEL_STATE_HOLD;
1882 message_put(message);
1884 new_state(EPOINT_STATE_OUT_OVERLAP);
1885 /* if we are in a join */
1886 if (ea_endpoint->ep_join_id)
1888 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1889 memcpy(&message->param, param, sizeof(union parameter));
1890 message_put(message);
1894 /* port MESSAGE_PROCEEDING */
1895 void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_type, union parameter *param)
1897 struct lcr_msg *message;
1899 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1901 /* signal to call tool */
1902 admin_call_response(e_adminid, ADMIN_CALL_PROCEEDING, "", 0, 0, 0);
1904 e_state = EPOINT_STATE_OUT_PROCEEDING;
1905 /* check if pattern is availatle */
1906 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
1908 /* indicate patterns */
1909 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1910 message_put(message);
1912 /* connect audio, if not already */
1913 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1914 message->param.audiopath = CHANNEL_STATE_CONNECT;
1915 message_put(message);
1918 /* indicate no patterns */
1919 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1920 message_put(message);
1922 /* disconnect audio, if not already */
1923 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1924 message->param.audiopath = CHANNEL_STATE_HOLD;
1925 message_put(message);
1927 /* if we are in a call */
1928 if (ea_endpoint->ep_join_id)
1930 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1931 memcpy(&message->param, param, sizeof(union parameter));
1932 message_put(message);
1936 /* port MESSAGE_ALERTING */
1937 void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type, union parameter *param)
1939 struct lcr_msg *message;
1941 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1943 /* signal to call tool */
1944 admin_call_response(e_adminid, ADMIN_CALL_ALERTING, "", 0, 0, 0);
1946 new_state(EPOINT_STATE_OUT_ALERTING);
1947 /* check if pattern is available */
1948 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
1950 /* indicate patterns */
1951 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1952 message_put(message);
1954 /* connect audio, if not already */
1955 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1956 message->param.audiopath = CHANNEL_STATE_CONNECT;
1957 message_put(message);
1960 /* indicate no patterns */
1961 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1962 message_put(message);
1964 /* disconnect audio, if not already */
1965 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1966 message->param.audiopath = CHANNEL_STATE_HOLD;
1967 message_put(message);
1969 /* if we are in a call */
1970 if (ea_endpoint->ep_join_id)
1972 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1973 memcpy(&message->param, param, sizeof(union parameter));
1974 message_put(message);
1978 /* port MESSAGE_CONNECT */
1979 void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, union parameter *param)
1981 struct lcr_msg *message;
1983 unsigned long port_id = portlist->port_id;
1984 struct port_list *tportlist;
1986 struct interface *interface;
1988 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1990 /* signal to call tool */
1991 admin_call_response(e_adminid, ADMIN_CALL_CONNECT, numberrize_callerinfo(param->connectinfo.id,param->connectinfo.ntype, options.national, options.international), 0, 0, 0);
1993 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_connectinfo));
1994 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (start)\n", ea_endpoint->ep_serial);
1995 while(ea_endpoint->ep_portlist->next) /* as long as we have at least two ports */
1997 tportlist = ea_endpoint->ep_portlist;
1998 if (tportlist->port_id == port_id) /* if the first portlist is the calling one, the second must be a different one */
1999 tportlist = tportlist->next;
2000 if (tportlist->port_id == port_id)
2001 FATAL("EPOINT(%d) this should not happen since the portlist list must not have two links to the same port - exitting.\n");
2002 message = message_create(ea_endpoint->ep_serial, tportlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2003 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
2004 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2005 message_put(message);
2006 logmessage(message->type, &message->param, tportlist->port_id, DIRECTION_OUT);
2007 ea_endpoint->free_portlist(tportlist);
2009 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (end)\n", ea_endpoint->ep_serial);
2013 /* screen incoming connected id */
2014 interface = interface_first;
2017 if (!strcmp(e_connectinfo.interface, interface->name))
2021 interface = interface->next;
2024 do_screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface);
2026 /* screen connected name */
2028 SCPY(e_connectinfo.name, e_ext.name);
2030 /* add internal id to colp */
2031 SCPY(e_connectinfo.extension, e_ext.number);
2033 /* we store the connected port number */
2034 SCPY(e_extension_interface, e_connectinfo.interface);
2036 /* for internal and am calls, we get the extension's id */
2037 if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE)
2039 SCPY(e_connectinfo.id, e_ext.callerid);
2040 SCPY(e_connectinfo.extension, e_ext.number);
2041 e_connectinfo.itype = INFO_ITYPE_ISDN_EXTENSION;
2042 e_connectinfo.ntype = e_ext.callerid_type;
2043 e_connectinfo.present = e_ext.callerid_present;
2045 if (portlist->port_type==PORT_TYPE_VBOX_OUT)
2047 e_connectinfo.itype = INFO_ITYPE_VBOX;
2048 e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2051 new_state(EPOINT_STATE_CONNECT);
2053 /* set volume of rx and tx */
2054 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
2056 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2057 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2058 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
2059 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
2060 message_put(message);
2063 e_cfnr_call = e_cfnr_release = 0;
2064 if (e_ext.number[0])
2065 e_dtmf = 1; /* allow dtmf */
2068 /* other calls with no caller id (or not available for the extension) and force colp */
2069 if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE)
2071 e_connectinfo.present = INFO_PRESENT_NOTAVAIL;
2072 if (portlist->port_type==PORT_TYPE_DSS1_TE_OUT || portlist->port_type==PORT_TYPE_DSS1_NT_OUT) /* external extension answered */
2074 port = find_port_id(portlist->port_id);
2077 SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.id, &e_connectinfo.ntype, options.national, options.international));
2078 e_connectinfo.present = INFO_PRESENT_ALLOWED;
2083 /* send connect to join */
2084 if (ea_endpoint->ep_join_id)
2086 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2087 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
2088 message_put(message);
2090 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2091 message->param.audiopath = CHANNEL_STATE_CONNECT;
2092 message_put(message);
2093 } else if (!e_adminid)
2096 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have a callback, so we create a call with cbcaller: \"%s\".\n", ea_endpoint->ep_serial, e_cbcaller);
2097 SCPY(e_ext.number, e_cbcaller);
2098 new_state(EPOINT_STATE_IN_OVERLAP);
2099 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) callback from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2101 /* get extension's info about terminal */
2102 if (!read_extension(&e_ext, e_ext.number))
2104 /* extension doesn't exist */
2105 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2106 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
2107 new_state(EPOINT_STATE_OUT_DISCONNECT);
2108 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
2112 /* put prefix in front of e_cbdialing */
2113 SPRINT(buffer, "%s%s", e_ext.prefix, e_cbdialing);
2114 SCPY(e_dialinginfo.id, buffer);
2115 e_dialinginfo.itype = INFO_ITYPE_ISDN;
2116 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
2118 /* use caller id (or if exist: id_next_call) for this call */
2119 e_callerinfo.screen = INFO_SCREEN_NETWORK;
2120 SCPY(e_callerinfo.extension, e_ext.number);
2121 if (e_ext.id_next_call_present >= 0)
2123 SCPY(e_callerinfo.id, e_ext.id_next_call);
2124 e_callerinfo.present = e_ext.id_next_call_present;
2125 e_callerinfo.ntype = e_ext.id_next_call_type;
2126 e_ext.id_next_call_present = -1;
2127 /* extension is written */
2128 write_extension(&e_ext, e_ext.number);
2131 SCPY(e_callerinfo.id, e_ext.callerid);
2132 e_callerinfo.present = e_ext.callerid_present;
2133 e_callerinfo.ntype = e_ext.callerid_type;
2136 e_connectedmode = 1; /* dtmf-hangup & disconnect prevention */
2139 /* check if caller id is NOT authenticated */
2140 if (!parse_callbackauth(e_ext.number, &e_callbackinfo))
2142 /* make call state to enter password */
2143 new_state(EPOINT_STATE_IN_OVERLAP);
2144 e_action = &action_password_write;
2145 e_match_timeout = 0;
2146 e_match_to_action = NULL;
2147 e_dialinginfo.id[0] = '\0';
2148 e_extdialing = strchr(e_dialinginfo.id, '\0');
2149 e_password_timeout = now+20;
2153 /* incoming call (callback) */
2154 e_ruleset = ruleset_main;
2156 e_rule = e_ruleset->rule_first;
2158 e_extdialing = e_dialinginfo.id;
2159 if (e_dialinginfo.id[0])
2161 set_tone(portlist, "dialing");
2165 set_tone(portlist, "dialpbx");
2168 } else /* testcall */
2170 set_tone(portlist, "hold");
2173 /* start recording if enabled, not when answering machine answers */
2174 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))
2176 /* check if we are a terminal */
2177 if (e_ext.number[0] == '\0')
2178 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
2181 port = find_port_id(portlist->port_id);
2183 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
2188 /* port MESSAGE_DISCONNECT MESSAGE_RELEASE */
2189 void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
2191 struct lcr_msg *message;
2193 unsigned long port_id = portlist->port_id;
2197 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2199 /* signal to call tool */
2200 admin_call_response(e_adminid, (message_type==MESSAGE_DISCONNECT)?ADMIN_CALL_DISCONNECT:ADMIN_CALL_RELEASE, "", param->disconnectinfo.cause, param->disconnectinfo.location, 0);
2202 //#warning does this work? only disconnect when incoming port hat not already disconnected yet?
2203 if (e_state==EPOINT_STATE_IN_DISCONNECT && message_type!=MESSAGE_RELEASE)// || e_state==EPOINT_STATE_OUT_DISCONNECT || e_state==EPOINT_STATE_IDLE)
2205 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are already disconnected.\n", ea_endpoint->ep_serial);
2210 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);
2211 collect_cause(&e_multipoint_cause, &e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location);
2212 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new multipoint cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location);
2214 /* check if we have more than one portlist relation and we just ignore the disconnect */
2215 if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist->next)
2217 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the disconnect was from a multipoint call. we just release that relation.\n", ea_endpoint->ep_serial);
2218 portlist = ea_endpoint->ep_portlist;
2221 if (portlist->port_id == port_id)
2223 portlist = portlist->next;
2226 FATAL("EPOINT(%d) no portlist related to the calling port.\n", ea_endpoint->ep_serial);
2227 if (message_type != MESSAGE_RELEASE)
2229 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2230 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2231 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2232 message_put(message);
2233 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2235 ea_endpoint->free_portlist(portlist);
2236 return; /* one relation removed */
2238 if (e_state == EPOINT_STATE_CONNECT)
2240 /* use cause from port after connect */
2241 cause = param->disconnectinfo.cause;
2242 location = param->disconnectinfo.location;
2245 /* use multipoint cause if no connect yet */
2246 if (e_multipoint_cause)
2248 cause = e_multipoint_cause;
2249 location = e_multipoint_location;
2252 cause = CAUSE_NOUSER;
2253 location = LOCATION_PRIVATE_LOCAL;
2257 e_cfnr_call = e_cfnr_release = 0;
2259 /* process hangup */
2260 process_hangup(e_join_cause, e_join_location);
2261 e_multipoint_cause = 0;
2262 e_multipoint_location = 0;
2264 if (message_type == MESSAGE_DISCONNECT)
2266 /* tone to disconnected end */
2267 SPRINT(buffer, "cause_%02x", cause);
2268 if (ea_endpoint->ep_portlist)
2269 set_tone(ea_endpoint->ep_portlist, buffer);
2271 new_state(EPOINT_STATE_IN_DISCONNECT);
2274 if (ea_endpoint->ep_join_id)
2276 int haspatterns = 0;
2277 /* check if pattern is available */
2278 if (ea_endpoint->ep_portlist)
2279 if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->early_b)
2280 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
2281 && message_type != MESSAGE_RELEASE) // if we release, we are done
2285 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has patterns.\n", ea_endpoint->ep_serial);
2286 /* indicate patterns */
2287 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2288 message_put(message);
2289 /* connect audio, if not already */
2290 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2291 message->param.audiopath = CHANNEL_STATE_CONNECT;
2292 message_put(message);
2293 /* send disconnect */
2294 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2295 memcpy(&message->param, param, sizeof(union parameter));
2296 message_put(message);
2297 /* disable encryption if disconnected */
2298 //PERROR("REMOVE ME: state =%d, %d\n", e_crypt_state, e_crypt);
2300 cryptman_message(CI_DISCONNECT_IND, NULL, 0);
2304 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
2307 if (message_type == MESSAGE_RELEASE)
2308 ea_endpoint->free_portlist(portlist);
2309 release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, callcause, portcause */
2310 return; /* must exit here */
2313 /* port MESSAGE_TIMEOUT */
2314 void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type, union parameter *param)
2318 trace_header("TIMEOUT", DIRECTION_IN);
2319 message_type = MESSAGE_DISCONNECT;
2320 switch (param->state)
2322 case PORT_STATE_OUT_SETUP:
2323 case PORT_STATE_OUT_OVERLAP:
2324 add_trace("state", NULL, "outgoing setup/dialing");
2326 /* no user responding */
2327 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2328 return; /* must exit here */
2330 case PORT_STATE_IN_SETUP:
2331 case PORT_STATE_IN_OVERLAP:
2332 add_trace("state", NULL, "incoming setup/dialing");
2333 param->disconnectinfo.cause = CAUSE_INVALID; /* number incomplete */
2334 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2337 case PORT_STATE_OUT_PROCEEDING:
2338 add_trace("state", NULL, "outgoing proceeding");
2340 param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
2341 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2342 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2343 return; /* must exit here */
2345 case PORT_STATE_IN_PROCEEDING:
2346 add_trace("state", NULL, "incoming proceeding");
2347 param->disconnectinfo.cause = CAUSE_NOUSER;
2348 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL; /* no user responding */
2351 case PORT_STATE_OUT_ALERTING:
2352 add_trace("state", NULL, "outgoing alerting");
2354 param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
2355 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2356 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2357 return; /* must exit here */
2359 case PORT_STATE_CONNECT:
2360 add_trace("state", NULL, "connect");
2362 param->disconnectinfo.cause = CAUSE_NORMAL; /* normal */
2363 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2364 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2365 return; /* must exit here */
2367 case PORT_STATE_IN_ALERTING:
2368 add_trace("state", NULL, "incoming alerting");
2369 param->disconnectinfo.cause = CAUSE_NOANSWER;
2370 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2373 case PORT_STATE_IN_DISCONNECT:
2374 case PORT_STATE_OUT_DISCONNECT:
2375 add_trace("state", NULL, "disconnect");
2377 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
2378 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2379 return; /* must exit here */
2382 param->disconnectinfo.cause = 31; /* normal unspecified */
2383 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2386 /* release call, disconnect isdn */
2388 new_state(EPOINT_STATE_OUT_DISCONNECT);
2389 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2390 SCPY(e_tone, cause);
2393 set_tone(portlist, cause);
2394 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2395 portlist = portlist->next;
2397 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
2400 /* port MESSAGE_NOTIFY */
2401 void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, union parameter *param)
2403 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2405 struct lcr_msg *message;
2409 /* signal to call tool */
2410 admin_call_response(e_adminid, ADMIN_CALL_NOTIFY, numberrize_callerinfo(param->notifyinfo.id,param->notifyinfo.ntype, options.national, options.international), 0, 0, param->notifyinfo.notify);
2411 if (param->notifyinfo.notify)
2413 e_rx_state = track_notify(e_rx_state, param->notifyinfo.notify);
2416 /* if we get notification from stack, local shows if we disabled/enabled audio stream */
2417 if (param->notifyinfo.local) switch(param->notifyinfo.notify)
2419 case INFO_NOTIFY_REMOTE_HOLD:
2420 case INFO_NOTIFY_USER_SUSPENDED:
2421 /* tell call about it */
2422 if (ea_endpoint->ep_join_id)
2424 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2425 message->param.audiopath = CHANNEL_STATE_HOLD;
2426 message_put(message);
2430 case INFO_NOTIFY_REMOTE_RETRIEVAL:
2431 case INFO_NOTIFY_USER_RESUMED:
2432 /* set volume of rx and tx */
2433 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
2434 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
2437 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2438 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2439 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
2440 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
2441 message_put(message);
2443 /* set current tone */
2445 set_tone(portlist, e_tone);
2446 /* tell call about it */
2447 if (ea_endpoint->ep_join_id)
2449 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2450 message->param.audiopath = CHANNEL_STATE_CONNECT;
2451 message_put(message);
2456 /* get name of notify */
2457 switch(param->notifyinfo.notify)
2463 logtext = "USER_SUSPENDED";
2466 logtext = "BEARER_SERVICE_CHANGED";
2469 logtext = "USER_RESUMED";
2472 logtext = "CONFERENCE_ESTABLISHED";
2475 logtext = "CONFERENCE_DISCONNECTED";
2478 logtext = "OTHER_PARTY_ADDED";
2481 logtext = "ISOLATED";
2484 logtext = "REATTACHED";
2487 logtext = "OTHER_PARTY_ISOLATED";
2490 logtext = "OTHER_PARTY_REATTACHED";
2493 logtext = "OTHER_PARTY_SPLIT";
2496 logtext = "OTHER_PARTY_DISCONNECTED";
2499 logtext = "CONFERENCE_FLOATING";
2502 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
2505 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
2508 logtext = "CALL_IS_A_WAITING_CALL";
2511 logtext = "DIVERSION_ACTIVATED";
2514 logtext = "RESERVED_CT_1";
2517 logtext = "RESERVED_CT_2";
2520 logtext = "REVERSE_CHARGING";
2523 logtext = "REMOTE_HOLD";
2526 logtext = "REMOTE_RETRIEVAL";
2529 logtext = "CALL_IS_DIVERTING";
2532 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
2537 /* notify call if available */
2538 if (ea_endpoint->ep_join_id)
2540 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOTIFY);
2541 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
2542 message_put(message);
2547 /* port MESSAGE_FACILITY */
2548 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
2550 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2552 struct lcr_msg *message;
2554 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_FACILITY);
2555 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2556 message_put(message);
2559 /* port MESSAGE_SUSPEND */
2560 /* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
2561 void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
2563 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2565 /* epoint is now parked */
2566 ea_endpoint->ep_park = 1;
2567 memcpy(ea_endpoint->ep_park_callid, param->parkinfo.callid, sizeof(ea_endpoint->ep_park_callid));
2568 ea_endpoint->ep_park_len = (param->parkinfo.len>8)?8:param->parkinfo.len;
2570 /* remove port relation */
2571 ea_endpoint->free_portlist(portlist);
2574 /* port MESSAGE_RESUME */
2575 /* NOTE: before resume, the active-notification must be done in order to set call mixer */
2576 void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
2578 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2580 /* epoint is now resumed */
2581 ea_endpoint->ep_park = 0;
2586 /* port sends message to the endpoint
2588 void EndpointAppPBX::ea_message_port(unsigned long port_id, int message_type, union parameter *param)
2590 struct port_list *portlist;
2591 struct lcr_msg *message;
2593 portlist = ea_endpoint->ep_portlist;
2596 if (port_id == portlist->port_id)
2598 portlist = portlist->next;
2602 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);
2606 // PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
2607 switch(message_type)
2609 case MESSAGE_DATA: /* data from port */
2610 /* check if there is a call */
2611 if (!ea_endpoint->ep_join_id)
2613 /* continue if only one portlist */
2614 if (ea_endpoint->ep_portlist->next != NULL)
2616 /* forward message */
2617 message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2620 case MESSAGE_TONE_EOF: /* tone is end of file */
2621 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
2624 if (e_action->index == ACTION_VBOX_PLAY)
2628 if (e_action->index == ACTION_EFI)
2635 case MESSAGE_TONE_COUNTER: /* counter info received */
2636 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);
2638 if (e_action->index == ACTION_VBOX_PLAY)
2640 e_vbox_counter = param->counter.current;
2641 if (param->counter.max >= 0)
2642 e_vbox_counter_max = param->counter.max;
2646 /* PORT sends SETUP message */
2648 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);
2649 if (e_state!=EPOINT_STATE_IDLE)
2651 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
2654 port_setup(portlist, message_type, param);
2657 /* PORT sends INFORMATION message */
2658 case MESSAGE_INFORMATION: /* additional digits received */
2659 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);
2660 port_information(portlist, message_type, param);
2663 /* PORT sends FACILITY message */
2664 case MESSAGE_FACILITY:
2665 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2666 port_facility(portlist, message_type, param);
2669 /* PORT sends DTMF message */
2670 case MESSAGE_DTMF: /* dtmf digits received */
2671 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);
2672 port_dtmf(portlist, message_type, param);
2675 /* PORT sends CRYPT message */
2676 case MESSAGE_CRYPT: /* crypt response received */
2677 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) crypt response=%d\n", ea_endpoint->ep_serial, param->crypt.type);
2678 port_crypt(portlist, message_type, param);
2681 /* PORT sends MORE message */
2682 case MESSAGE_OVERLAP:
2683 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);
2684 if (e_state != EPOINT_STATE_OUT_SETUP)
2686 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);
2689 port_overlap(portlist, message_type, param);
2692 /* PORT sends PROCEEDING message */
2693 case MESSAGE_PROCEEDING: /* port is proceeding */
2694 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);
2695 if (e_state!=EPOINT_STATE_OUT_SETUP
2696 && e_state!=EPOINT_STATE_OUT_OVERLAP)
2698 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);
2701 port_proceeding(portlist, message_type, param);
2704 /* PORT sends ALERTING message */
2705 case MESSAGE_ALERTING:
2706 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);
2707 if (e_state!=EPOINT_STATE_OUT_SETUP
2708 && e_state!=EPOINT_STATE_OUT_OVERLAP
2709 && e_state!=EPOINT_STATE_OUT_PROCEEDING)
2711 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);
2714 port_alerting(portlist, message_type, param);
2717 /* PORT sends CONNECT message */
2718 case MESSAGE_CONNECT:
2719 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);
2720 if (e_state!=EPOINT_STATE_OUT_SETUP
2721 && e_state!=EPOINT_STATE_OUT_OVERLAP
2722 && e_state!=EPOINT_STATE_OUT_PROCEEDING
2723 && e_state!=EPOINT_STATE_OUT_ALERTING)
2725 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
2728 port_connect(portlist, message_type, param);
2731 /* PORT sends DISCONNECT message */
2732 case MESSAGE_DISCONNECT: /* port is disconnected */
2733 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);
2734 port_disconnect_release(portlist, message_type, param);
2737 /* PORT sends a RELEASE message */
2738 case MESSAGE_RELEASE: /* port releases */
2739 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);
2740 /* portlist is release at port_disconnect_release, thanx Paul */
2741 port_disconnect_release(portlist, message_type, param);
2744 /* PORT sends a TIMEOUT message */
2745 case MESSAGE_TIMEOUT:
2746 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);
2747 port_timeout(portlist, message_type, param);
2748 break; /* release */
2750 /* PORT sends a NOTIFY message */
2751 case MESSAGE_NOTIFY:
2752 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);
2753 port_notify(portlist, message_type, param);
2756 /* PORT sends a SUSPEND message */
2757 case MESSAGE_SUSPEND:
2758 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);
2759 port_suspend(portlist, message_type, param);
2760 break; /* suspend */
2762 /* PORT sends a RESUME message */
2763 case MESSAGE_RESUME:
2764 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);
2765 port_resume(portlist, message_type, param);
2769 kann nach dem test gelöscht werden, da eine direkte funktion im join und im mISDN zum austausch der message existiert
2770 /* port assigns bchannel */
2771 case MESSAGE_BCHANNEL: /* bchannel assignment messafe */
2772 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);
2773 /* only one port is expected to be connected to bchannel */
2774 message = message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2775 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_IN);
2781 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);
2784 /* Note: this endpoint may be destroyed, so we MUST return */
2788 /* messages from join
2790 /* join MESSAGE_CRYPT */
2791 void EndpointAppPBX::join_crypt(struct port_list *portlist, int message_type, union parameter *param)
2793 switch(param->crypt.type)
2795 /* message from remote port to "crypt manager" */
2796 case CU_ACTK_REQ: /* activate key-exchange */
2797 case CU_ACTS_REQ: /* activate shared key */
2798 case CU_DACT_REQ: /* deactivate */
2799 case CU_INFO_REQ: /* request last info message */
2800 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2803 /* message from "crypt manager" to user */
2804 case CU_ACTK_CONF: /* key-echange done */
2805 case CU_ACTS_CONF: /* shared key done */
2806 case CU_DACT_CONF: /* deactivated */
2807 case CU_DACT_IND: /* deactivated */
2808 case CU_ERROR_IND: /* receive error message */
2809 case CU_INFO_IND: /* receive info message */
2810 case CU_INFO_CONF: /* receive info message */
2811 encrypt_result(param->crypt.type, (char *)param->crypt.data);
2815 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);
2819 /* join MESSAGE_INFORMATION */
2820 void EndpointAppPBX::join_information(struct port_list *portlist, int message_type, union parameter *param)
2822 struct lcr_msg *message;
2828 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2829 memcpy(&message->param.information, ¶m->information, sizeof(struct dialing_info));
2830 message_put(message);
2831 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2832 portlist = portlist->next;
2836 /* join MESSAGE_FACILITY */
2837 void EndpointAppPBX::join_facility(struct port_list *portlist, int message_type, union parameter *param)
2839 struct lcr_msg *message;
2841 if (!e_ext.facility && e_ext.number[0])
2848 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_FACILITY);
2849 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2850 message_put(message);
2851 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2852 portlist = portlist->next;
2856 /* join MESSAGE_MORE */
2857 void EndpointAppPBX::join_overlap(struct port_list *portlist, int message_type, union parameter *param)
2859 struct lcr_msg *message;
2861 new_state(EPOINT_STATE_IN_OVERLAP);
2864 if (e_join_pattern && e_ext.own_setup)
2866 /* disconnect audio */
2867 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2868 message->param.audiopath = CHANNEL_STATE_HOLD;
2869 message_put(message);
2871 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
2873 if (e_dialinginfo.id[0])
2874 set_tone(portlist, "dialing");
2876 set_tone(portlist, "dialtone");
2879 if (e_ext.number[0])
2880 set_tone(portlist, "dialpbx");
2882 set_tone(portlist, "dialtone");
2885 /* join MESSAGE_PROCEEDING */
2886 void EndpointAppPBX::join_proceeding(struct port_list *portlist, int message_type, union parameter *param)
2888 struct lcr_msg *message;
2890 new_state(EPOINT_STATE_IN_PROCEEDING);
2892 /* own proceeding tone */
2895 /* connect / disconnect audio */
2896 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2897 if (e_ext.own_proceeding)
2898 message->param.audiopath = CHANNEL_STATE_HOLD;
2900 message->param.audiopath = CHANNEL_STATE_CONNECT;
2901 message_put(message);
2903 // UCPY(e_join_tone, "proceeding");
2906 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
2907 message_put(message);
2908 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2910 set_tone(portlist, "proceeding");
2913 /* join MESSAGE_ALERTING */
2914 void EndpointAppPBX::join_alerting(struct port_list *portlist, int message_type, union parameter *param)
2916 struct lcr_msg *message;
2918 new_state(EPOINT_STATE_IN_ALERTING);
2920 /* own alerting tone */
2923 /* connect / disconnect audio */
2924 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2925 if (e_ext.own_alerting)
2926 message->param.audiopath = CHANNEL_STATE_HOLD;
2928 message->param.audiopath = CHANNEL_STATE_CONNECT;
2929 message_put(message);
2933 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
2934 message_put(message);
2935 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2937 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
2939 set_tone(portlist, "ringing");
2942 if (e_ext.number[0])
2943 set_tone(portlist, "ringpbx");
2945 set_tone(portlist, "ringing");
2948 /* join MESSAGE_CONNECT */
2949 void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type, union parameter *param)
2951 struct lcr_msg *message;
2953 new_state(EPOINT_STATE_CONNECT);
2954 // UCPY(e_join_tone, "");
2955 if (e_ext.number[0])
2956 e_dtmf = 1; /* allow dtmf */
2958 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_callerinfo));
2961 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
2962 memcpy(&message->param, param, sizeof(union parameter));
2964 /* screen clip if prefix is required */
2965 if (e_ext.number[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0])
2967 SCPY(message->param.connectinfo.id, e_ext.clip_prefix);
2968 SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype, options.national, options.international));
2969 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2972 /* use internal caller id */
2973 if (e_ext.number[0] && e_connectinfo.extension[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
2975 SCPY(message->param.connectinfo.id, e_connectinfo.extension);
2976 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2979 /* handle restricted caller ids */
2980 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);
2981 /* display callerid if desired for extension */
2982 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));
2984 /* use conp, if enabld */
2985 // if (!e_ext.centrex)
2986 // message->param.connectinfo.name[0] = '\0';
2989 message_put(message);
2990 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2992 set_tone(portlist, NULL);
2994 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2995 message->param.audiopath = CHANNEL_STATE_CONNECT;
2996 message_put(message);
3000 /* join MESSAGE_DISCONNECT MESSAGE_RELEASE */
3001 void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *param)
3004 struct lcr_msg *message;
3005 struct port_list *portlist = NULL;
3008 /* be sure that we are active */
3010 e_tx_state = NOTIFY_STATE_ACTIVE;
3012 /* we are powerdialing, if e_powerdialing is set and limit is not exceeded if given */
3013 if (e_powerdialing && ((e_powercount+1)<e_powerlimit || e_powerlimit<1))
3015 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
3017 /* set time for power dialing */
3018 e_powerdialing = now_d + e_powerdelay; /* set redial in the future */
3021 /* set redial tone */
3022 if (ea_endpoint->ep_portlist)
3026 set_tone(ea_endpoint->ep_portlist, "redial");
3027 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);
3028 /* send proceeding when powerdialing and still setup (avoid dialing timeout) */
3029 if (e_state==EPOINT_STATE_IN_OVERLAP)
3031 new_state(EPOINT_STATE_IN_PROCEEDING);
3032 if (ea_endpoint->ep_portlist)
3034 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3035 message_put(message);
3036 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3038 /* caused the error, that the first knock sound was not there */
3039 /* set_tone(portlist, "proceeding"); */
3041 /* send display of powerdialing */
3042 if (e_ext.display_dialing)
3044 portlist = ea_endpoint->ep_portlist;
3047 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3049 SPRINT(message->param.notifyinfo.display, "Retry %d of %d", e_powercount, e_powerlimit);
3051 SPRINT(message->param.notifyinfo.display, "Retry %d", e_powercount);
3052 message_put(message);
3053 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3054 portlist = portlist->next;
3063 if ((e_state!=EPOINT_STATE_CONNECT
3064 && e_state!=EPOINT_STATE_OUT_DISCONNECT
3065 && e_state!=EPOINT_STATE_IN_OVERLAP
3066 && e_state!=EPOINT_STATE_IN_PROCEEDING
3067 && e_state!=EPOINT_STATE_IN_ALERTING)
3068 || !ea_endpoint->ep_portlist) /* or no port */
3070 process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
3071 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause); /* RELEASE_TYPE, join, port */
3072 return; /* must exit here */
3077 e_join_cause = param->disconnectinfo.cause;
3078 e_join_location = param->disconnectinfo.location;
3081 /* on release we need the audio again! */
3082 if (message_type == MESSAGE_RELEASE)
3085 ea_endpoint->ep_join_id = 0;
3087 /* disconnect and select tone */
3088 new_state(EPOINT_STATE_OUT_DISCONNECT);
3089 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
3090 /* if own_cause, we must release the join */
3091 if (e_ext.own_cause /* own cause */
3092 || !e_join_pattern) /* no patterns */
3094 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);
3095 if (message_type != MESSAGE_RELEASE)
3096 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
3098 } else /* else we enable audio */
3100 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3101 message->param.audiopath = CHANNEL_STATE_CONNECT;
3102 message_put(message);
3104 /* send disconnect message */
3105 SCPY(e_tone, cause);
3106 portlist = ea_endpoint->ep_portlist;
3109 set_tone(portlist, cause);
3110 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
3111 portlist = portlist->next;
3115 /* join MESSAGE_SETUP */
3116 void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, union parameter *param)
3118 struct lcr_msg *message;
3119 // struct interface *interface;
3121 /* if we already in setup state, we just update the dialing with new digits */
3122 if (e_state == EPOINT_STATE_OUT_SETUP
3123 || e_state == EPOINT_STATE_OUT_OVERLAP)
3125 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we are in setup state, so we do overlap dialing.\n", ea_endpoint->ep_serial);
3126 /* if digits changed, what we have already dialed */
3127 if (!!strncmp(e_dialinginfo.id,param->setup.dialinginfo.id,strlen(e_dialinginfo.id)))
3129 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have dialed digits which have been changed or we have a new multidial, so we must redial.\n", ea_endpoint->ep_serial);
3130 /* release all ports */
3131 while((portlist = ea_endpoint->ep_portlist))
3133 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
3134 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
3135 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3136 message_put(message);
3137 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3138 ea_endpoint->free_portlist(portlist);
3141 /* disconnect audio */
3142 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3143 message->param.audiopath = CHANNEL_STATE_HOLD;
3144 message_put(message);
3146 /* get dialing info */
3147 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3148 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3149 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3150 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3151 new_state(EPOINT_STATE_OUT_OVERLAP);
3154 e_redial = now_d + 1; /* set redial one second in the future */
3157 /* if we have a pending redial, so we just adjust the dialing number */
3160 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) redial in progress, so we update the dialing number to %s.\n", ea_endpoint->ep_serial, param->setup.dialinginfo.id);
3161 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3164 if (!ea_endpoint->ep_portlist)
3166 PERROR("ERROR: overlap dialing to a NULL port relation\n");
3168 if (ea_endpoint->ep_portlist->next)
3170 PERROR("ERROR: overlap dialing to a port_list port relation\n");
3172 if (e_state == EPOINT_STATE_OUT_SETUP)
3175 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) digits '%s' are queued because we didn't receive a setup acknowledge.\n", ea_endpoint->ep_serial, param->setup.dialinginfo.id);
3176 SCAT(e_dialing_queue, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3180 /* get what we have not dialed yet */
3181 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have already dialed '%s', we received '%s', what's left '%s'.\n", ea_endpoint->ep_serial, e_dialinginfo.id, param->setup.dialinginfo.id, param->setup.dialinginfo.id+strlen(e_dialinginfo.id));
3182 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
3183 SCPY(message->param.information.id, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3184 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
3185 message_put(message);
3186 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3188 /* always store what we have dialed or queued */
3189 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3193 if (e_state != EPOINT_STATE_IDLE)
3195 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
3198 /* if an internal extension is dialed, copy that number */
3199 if (param->setup.dialinginfo.itype==INFO_ITYPE_ISDN_EXTENSION || param->setup.dialinginfo.itype==INFO_ITYPE_VBOX)
3200 SCPY(e_ext.number, param->setup.dialinginfo.id);
3201 /* if an internal extension is dialed, get extension's info about caller */
3202 if (e_ext.number[0])
3204 if (!read_extension(&e_ext, e_ext.number))
3206 e_ext.number[0] = '\0';
3207 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the called terminal='%s' is not found in directory tree!\n", ea_endpoint->ep_serial, e_ext.number);
3211 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3212 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3213 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3214 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3216 /* process (voice over) data calls */
3217 if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO)
3219 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) handling data call as audio call: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
3220 memset(&e_capainfo, 0, sizeof(e_capainfo));
3221 e_capainfo.bearer_capa = INFO_BC_AUDIO;
3222 e_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
3223 e_capainfo.bearer_info1 = (options.law=='u')?INFO_INFO1_ULAW:INFO_INFO1_ALAW;
3226 new_state(EPOINT_STATE_OUT_SETUP);
3227 /* call special setup routine */
3231 /* join MESSAGE_mISDNSIGNAL */
3232 void EndpointAppPBX::join_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param)
3234 struct lcr_msg *message;
3238 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
3239 memcpy(&message->param, param, sizeof(union parameter));
3240 message_put(message);
3241 portlist = portlist->next;
3245 /* join MESSAGE_NOTIFY */
3246 void EndpointAppPBX::join_notify(struct port_list *portlist, int message_type, union parameter *param)
3248 struct lcr_msg *message;
3251 if (param->notifyinfo.notify)
3253 new_state = track_notify(e_tx_state, param->notifyinfo.notify);
3254 // /* if notification was generated locally, we turn hold music on/off */
3255 // if (param->notifyinfo.local)
3256 // NOTE: we always assume that we send hold music on suspension of call, because we don't track if audio is available or not (we assume that we always have no audio, to make it easier)
3261 if (new_state!=NOTIFY_STATE_HOLD && new_state!=NOTIFY_STATE_SUSPEND)
3263 if (!strcmp(e_tone, "hold")) // don't interrupt other tones
3267 set_tone(portlist, "");
3268 portlist = portlist->next;
3271 portlist = ea_endpoint->ep_portlist;
3276 if (new_state==NOTIFY_STATE_HOLD || new_state==NOTIFY_STATE_SUSPEND)
3280 set_tone(portlist, "hold");
3281 portlist = portlist->next;
3283 portlist = ea_endpoint->ep_portlist;
3288 /* save new state */
3289 e_tx_state = new_state;
3292 /* notify port(s) about it */
3295 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3296 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
3297 /* handle restricted caller ids */
3298 apply_callerid_restriction(&e_ext, message->param.notifyinfo.id, &message->param.notifyinfo.ntype, &message->param.notifyinfo.present, 0, message->param.notifyinfo.extension, NULL);
3299 /* display callerid if desired for extension */
3300 SCPY(message->param.notifyinfo.display, apply_callerid_display(message->param.notifyinfo.id, message->param.notifyinfo.itype, message->param.notifyinfo.ntype, message->param.notifyinfo.present, 0, message->param.notifyinfo.extension, NULL));
3301 message_put(message);
3302 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3303 portlist = portlist->next;
3307 /* JOIN sends messages to the endpoint
3309 void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, union parameter *param)
3311 struct port_list *portlist;
3312 struct lcr_msg *message;
3316 PERROR("EPOINT(%d) error: JOIN == NULL.\n", ea_endpoint->ep_serial);
3320 portlist = ea_endpoint->ep_portlist;
3322 /* send MESSAGE_DATA to port */
3323 if (message_type == MESSAGE_DATA)
3325 if (join_id == ea_endpoint->ep_join_id) // still linked with JOIN
3327 /* skip if no port relation */
3330 /* skip if more than one port relation */
3333 /* forward audio data to port */
3334 message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3339 // PDEBUG(DEBUG_EPOINT, "EPOINT(%d) received message %d for active JOIN (terminal %s, caller id %s state=%d)\n", ea_endpoint->ep_serial, message, e_ext.number, e_callerinfo.id, e_state);
3340 switch(message_type)
3342 /* JOIN SENDS TONE message */
3344 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received tone message: '%d'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->tone.name);
3345 set_tone(portlist, param->tone.name);
3348 /* JOIN SENDS CRYPT message */
3350 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received crypt message: '%d'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->crypt.type);
3351 join_crypt(portlist, message_type, param);
3354 /* JOIN sends INFORMATION message */
3355 case MESSAGE_INFORMATION:
3356 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received more digits: '%s'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->information.id);
3357 join_information(portlist, message_type, param);
3360 /* JOIN sends FACILITY message */
3361 case MESSAGE_FACILITY:
3362 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received facility\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3363 join_facility(portlist, message_type, param);
3366 /* JOIN sends OVERLAP message */
3367 case MESSAGE_OVERLAP:
3368 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received 'more info available'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3369 if (e_state!=EPOINT_STATE_IN_SETUP
3370 && e_state!=EPOINT_STATE_IN_OVERLAP)
3372 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3375 join_overlap(portlist, message_type, param);
3378 /* JOIN sends PROCEEDING message */
3379 case MESSAGE_PROCEEDING:
3380 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s (caller id '%s') received proceeding\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3381 if(e_state!=EPOINT_STATE_IN_OVERLAP)
3383 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3386 join_proceeding(portlist, message_type, param);
3389 /* JOIN sends ALERTING message */
3390 case MESSAGE_ALERTING:
3391 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received alerting\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3392 if (e_state!=EPOINT_STATE_IN_OVERLAP
3393 && e_state!=EPOINT_STATE_IN_PROCEEDING)
3395 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state.\n", ea_endpoint->ep_serial);
3398 join_alerting(portlist, message_type, param);
3401 /* JOIN sends CONNECT message */
3402 case MESSAGE_CONNECT:
3403 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received connect\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3404 if (e_state!=EPOINT_STATE_IN_OVERLAP
3405 && e_state!=EPOINT_STATE_IN_PROCEEDING
3406 && e_state!=EPOINT_STATE_IN_ALERTING)
3408 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
3411 join_connect(portlist, message_type, param);
3414 /* JOIN sends DISCONNECT/RELEASE message */
3415 case MESSAGE_DISCONNECT: /* JOIN disconnect */
3416 case MESSAGE_RELEASE: /* JOIN releases */
3417 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received %s with cause %d location %d\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, (message_type==MESSAGE_DISCONNECT)?"disconnect":"release", param->disconnectinfo.cause, param->disconnectinfo.location);
3418 join_disconnect_release(message_type, param);
3421 /* JOIN sends SETUP message */
3423 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint received setup from terminal='%s',id='%s' to id='%s' (dialing itype=%d)\n", ea_endpoint->ep_serial, param->setup.callerinfo.extension, param->setup.callerinfo.id, param->setup.dialinginfo.id, param->setup.dialinginfo.itype);
3424 join_setup(portlist, message_type, param);
3427 /* JOIN sends special mISDNSIGNAL message */
3428 case MESSAGE_mISDNSIGNAL: /* isdn message to port */
3429 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received mISDNsignal message.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3430 join_mISDNsignal(portlist, message_type, param);
3434 kann nach dem test gelöscht werden, da eine direkte funktion im join und im mISDN zum austausch der message existiert
3435 /* JOIN requests bchannel */
3436 case MESSAGE_BCHANNEL: /* indicates the need of own bchannel access */
3437 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received bchannel assignment %d from join.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->bchannel.type);
3438 /* only one port is expected to be connected to bchannel */
3445 set_tone(portlist, NULL);
3446 message = message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3447 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3451 /* JOIN has pattern available */
3452 case MESSAGE_PATTERN: /* indicating pattern available */
3453 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received pattern availability.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3454 if (!e_join_pattern)
3456 PDEBUG(DEBUG_EPOINT, "-> pattern becomes available\n");
3461 set_tone(portlist, NULL);
3462 portlist = portlist->next;
3464 /* connect our audio tx and rx (blueboxing should be possibe before connect :)*/
3465 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3466 message->param.audiopath = CHANNEL_STATE_CONNECT;
3467 message_put(message);
3468 // /* tell remote epoint to connect audio also, because we like to hear the patterns */
3469 // message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_REMOTE_AUDIO);
3470 // message->param.audiopath = CHANNEL_STATE_CONNECT;
3471 // message_put(message);
3472 // patterns are available, remote already connected audio
3476 /* JOIN has no pattern available */
3477 case MESSAGE_NOPATTERN: /* indicating no pattern available */
3478 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received pattern NOT available.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3481 PDEBUG(DEBUG_EPOINT, "-> pattern becomes unavailable\n");
3483 /* disconnect our audio tx and rx */
3484 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3485 message->param.audiopath = CHANNEL_STATE_HOLD;
3486 message_put(message);
3491 /* JOIN (dunno at the moment) */
3492 case MESSAGE_REMOTE_AUDIO:
3493 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received audio remote request.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3494 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3495 message->param.audiopath = param->channel;
3496 message_put(message);
3500 /* JOIN sends a notify message */
3501 case MESSAGE_NOTIFY:
3502 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);
3503 join_notify(portlist, message_type, param);
3507 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);
3512 /* pick_join will connect the first incoming call found. the endpoint
3513 * will receivce a MESSAGE_CONNECT.
3515 int match_list(char *list, char *item)
3517 char *end, *next = NULL;
3519 /* no list make matching */
3525 /* eliminate white spaces */
3526 while (*list <= ' ')
3533 /* if end of list is reached, we return */
3534 if (list[0] == '\0')
3536 /* if we have more than one entry (left) */
3537 if ((end = strchr(list, ',')))
3540 next = end = strchr(list, '\0');
3541 while (*(end-1) <= ' ')
3543 /* if string part matches item */
3544 if (!strncmp(list, item, end-list))
3550 void EndpointAppPBX::pick_join(char *extensions)
3552 struct lcr_msg *message;
3553 struct port_list *portlist;
3555 class EndpointAppPBX *eapp, *found;
3557 class JoinPBX *joinpbx;
3558 struct join_relation *relation;
3561 /* find an endpoint that is ringing internally or vbox with higher priority */
3564 eapp = apppbx_first;
3567 if (eapp!=this && ea_endpoint->ep_portlist)
3569 portlist = eapp->ea_endpoint->ep_portlist;
3572 if ((port = find_port_id(portlist->port_id)))
3574 if (port->p_type == PORT_TYPE_VBOX_OUT)
3576 if (match_list(extensions, eapp->e_ext.number))
3583 if ((port->p_type==PORT_TYPE_DSS1_NT_OUT || port->p_type==PORT_TYPE_DSS1_TE_OUT)
3584 && port->p_state==PORT_STATE_OUT_ALERTING)
3585 if (match_list(extensions, eapp->e_ext.number))
3590 portlist = portlist->next;
3598 /* if no endpoint found */
3601 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) nobody is ringing internally (or we don't have her in the access list), so we disconnect.\n", ea_endpoint->ep_serial);
3603 set_tone(ea_endpoint->ep_portlist, "cause_10");
3604 message_disconnect_port(ea_endpoint->ep_portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
3605 new_state(EPOINT_STATE_OUT_DISCONNECT);
3610 if (ea_endpoint->ep_join_id)
3612 PERROR("EPOINT(%d) we already have a join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3615 if (!eapp->ea_endpoint->ep_join_id)
3617 PERROR("EPOINT(%d) ringing endpoint has no join.\n", ea_endpoint->ep_serial);
3620 join = find_join_id(eapp->ea_endpoint->ep_join_id);
3623 PERROR("EPOINT(%d) ringing endpoint's join not found.\n", ea_endpoint->ep_serial);
3626 if (join->j_type != JOIN_TYPE_PBX)
3628 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ringing endpoint's join is not a PBX join, so we must reject.\n", ea_endpoint->ep_serial);
3631 joinpbx = (class JoinPBX *)join;
3632 relation = joinpbx->j_relation;
3635 PERROR("EPOINT(%d) ringing endpoint's join has no relation. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3638 while (relation->epoint_id != eapp->ea_endpoint->ep_serial)
3640 relation = relation->next;
3643 PERROR("EPOINT(%d) ringing endpoint's join has no relation to that join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3648 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found ringing endpoint: %d.\n", ea_endpoint->ep_serial, eapp->ea_endpoint->ep_serial);
3650 if (options.deb & DEBUG_EPOINT)
3652 class Join *debug_c = join_first;
3653 class Endpoint *debug_e = epoint_first;
3654 class Port *debug_p = port_first;
3656 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(before)");
3658 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3661 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3662 debug_c = debug_c->next;
3664 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3667 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3668 debug_e = debug_e->next;
3670 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3673 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld (active)\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3674 debug_p = debug_p->next;
3679 ea_endpoint->ep_join_id = eapp->ea_endpoint->ep_join_id; /* we get the join */
3680 relation->epoint_id = ea_endpoint->ep_serial; /* the join gets us */
3681 eapp->ea_endpoint->ep_join_id = 0; /* the ringing endpoint will get disconnected */
3683 /* connnecting our endpoint */
3684 new_state(EPOINT_STATE_CONNECT);
3686 set_tone(ea_endpoint->ep_portlist, NULL);
3688 /* now we send a release to the ringing endpoint */
3689 message = message_create(ea_endpoint->ep_join_id, eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3690 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
3691 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3692 message_put(message);
3694 /* we send a connect to the join with our caller id */
3695 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CONNECT);
3696 SCPY(message->param.connectinfo.id, e_callerinfo.id);
3697 message->param.connectinfo.present = e_callerinfo.present;
3698 message->param.connectinfo.screen = e_callerinfo.screen;
3699 message->param.connectinfo.itype = e_callerinfo.itype;
3700 message->param.connectinfo.ntype = e_callerinfo.ntype;
3701 message_put(message);
3703 /* we send a connect to our port with the remote callerid */
3704 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3705 SCPY(message->param.connectinfo.id, eapp->e_callerinfo.id);
3706 message->param.connectinfo.present = eapp->e_callerinfo.present;
3707 message->param.connectinfo.screen = eapp->e_callerinfo.screen;
3708 message->param.connectinfo.itype = eapp->e_callerinfo.itype;
3709 message->param.connectinfo.ntype = eapp->e_callerinfo.ntype;
3710 /* handle restricted caller ids */
3711 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);
3712 /* display callerid if desired for extension */
3713 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));
3714 message_put(message);
3716 /* we send a connect to the audio path (not for vbox) */
3717 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3718 message->param.audiopath = CHANNEL_STATE_CONNECT;
3719 message_put(message);
3721 /* beeing paranoid, we make call update */
3722 joinpbx->j_updatebridge = 1;
3724 if (options.deb & DEBUG_EPOINT)
3726 class Join *debug_c = join_first;
3727 class Endpoint *debug_e = epoint_first;
3728 class Port *debug_p = port_first;
3730 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(after)");
3732 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3735 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3736 debug_c = debug_c->next;
3738 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3741 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3742 debug_e = debug_e->next;
3744 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3747 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3748 debug_p = debug_p->next;
3754 /* join calls (look for a join that is on hold (same isdn interface/terminal))
3756 void EndpointAppPBX::join_join(void)
3758 struct lcr_msg *message;
3759 struct join_relation *our_relation, *other_relation;
3760 struct join_relation **our_relation_pointer, **other_relation_pointer;
3761 class Join *our_join, *other_join;
3762 class JoinPBX *our_joinpbx, *other_joinpbx;
3763 class EndpointAppPBX *other_eapp; class Endpoint *temp_epoint;
3764 class Port *our_port, *other_port;
3765 class Pdss1 *our_pdss1, *other_pdss1;
3767 /* are we a candidate to join a join */
3768 our_join = find_join_id(ea_endpoint->ep_join_id);
3771 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3774 if (our_join->j_type != JOIN_TYPE_PBX)
3776 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: join is not a pbx join.\n", ea_endpoint->ep_serial);
3779 our_joinpbx = (class JoinPBX *)our_join;
3780 if (!ea_endpoint->ep_portlist)
3782 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
3785 if (!e_ext.number[0])
3787 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
3790 our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
3793 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
3796 if ((our_port->p_type&PORT_CLASS_mISDN_MASK) != PORT_CLASS_mISDN_DSS1)
3798 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not isdn.\n", ea_endpoint->ep_serial);
3801 our_pdss1 = (class Pdss1 *)our_port;
3803 /* find an endpoint that is on hold and has the same mISDNport that we are on */
3804 other_eapp = apppbx_first;
3807 if (other_eapp == this)
3809 other_eapp = other_eapp->next;
3812 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint candiate: (ep%d) terminal='%s' port=%s join=%d.\n", ea_endpoint->ep_serial, other_eapp->ea_endpoint->ep_serial, other_eapp->e_ext.number, (other_eapp->ea_endpoint->ep_portlist)?"YES":"NO", other_eapp->ea_endpoint->ep_join_id);
3813 if (other_eapp->e_ext.number[0] /* has terminal */
3814 && other_eapp->ea_endpoint->ep_portlist /* has port */
3815 && other_eapp->ea_endpoint->ep_join_id) /* has join */
3817 other_port = find_port_id(other_eapp->ea_endpoint->ep_portlist->port_id);
3818 if (other_port) /* port still exists */
3820 if (other_port->p_type==PORT_TYPE_DSS1_NT_OUT
3821 || other_port->p_type==PORT_TYPE_DSS1_NT_IN) /* port is isdn nt-mode */
3823 other_pdss1 = (class Pdss1 *)other_port;
3824 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of type isdn! comparing our portnum=%d with other's portnum=%d hold=%s ces=%d\n", ea_endpoint->ep_serial, our_pdss1->p_m_mISDNport->portnum, other_pdss1->p_m_mISDNport->portnum, (other_pdss1->p_m_hold)?"YES":"NO", other_pdss1->p_m_d_ces);
3825 if (other_pdss1->p_m_hold /* port is on hold */
3826 && other_pdss1->p_m_mISDNport == our_pdss1->p_m_mISDNport /* same isdn interface */
3827 && other_pdss1->p_m_d_ces == our_pdss1->p_m_d_ces) /* same tei+sapi */
3831 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of other type!\n", ea_endpoint->ep_serial);
3835 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port doesn't exist enymore.\n", ea_endpoint->ep_serial);
3838 other_eapp = other_eapp->next;
3842 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn interface with port on hold.\n", ea_endpoint->ep_serial);
3845 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port on hold found.\n", ea_endpoint->ep_serial);
3847 /* if we have the same join */
3848 if (other_eapp->ea_endpoint->ep_join_id == ea_endpoint->ep_join_id)
3850 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we an the other have the same join.\n", ea_endpoint->ep_serial);
3853 other_join = find_join_id(other_eapp->ea_endpoint->ep_join_id);
3856 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3859 if (other_join->j_type != JOIN_TYPE_PBX)
3861 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join is not a pbx join.\n", ea_endpoint->ep_serial);
3864 other_joinpbx = (class JoinPBX *)other_join;
3865 if (our_joinpbx->j_partyline && other_joinpbx->j_partyline)
3867 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both joins are partylines.\n", ea_endpoint->ep_serial);
3871 /* remove relation to endpoint for join on hold */
3872 other_relation = other_joinpbx->j_relation;
3873 other_relation_pointer = &other_joinpbx->j_relation;
3874 while(other_relation)
3876 if (other_relation->epoint_id == other_eapp->ea_endpoint->ep_serial)
3878 /* detach other endpoint on hold */
3879 *other_relation_pointer = other_relation->next;
3880 FREE(other_relation, sizeof(struct join_relation));
3882 other_relation = *other_relation_pointer;
3883 other_eapp->ea_endpoint->ep_join_id = 0;
3887 /* change join/hold pointer of endpoint to the new join */
3888 temp_epoint = find_epoint_id(other_relation->epoint_id);
3891 if (temp_epoint->ep_join_id == other_join->j_serial)
3892 temp_epoint->ep_join_id = our_join->j_serial;
3895 other_relation_pointer = &other_relation->next;
3896 other_relation = other_relation->next;
3898 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint on hold removed, other enpoints on join relinked (to our join).\n", ea_endpoint->ep_serial);
3900 /* join call relations */
3901 our_relation = our_joinpbx->j_relation;
3902 our_relation_pointer = &our_joinpbx->j_relation;
3905 our_relation_pointer = &our_relation->next;
3906 our_relation = our_relation->next;
3908 *our_relation_pointer = other_joinpbx->j_relation;
3909 other_joinpbx->j_relation = NULL;
3910 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) relations joined.\n", ea_endpoint->ep_serial);
3912 /* release endpoint on hold */
3913 message = message_create(other_joinpbx->j_serial, other_eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3914 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */
3915 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3916 message_put(message);
3918 /* if we are not a partyline, we get partyline state from other join */
3919 our_joinpbx->j_partyline += other_joinpbx->j_partyline;
3921 /* remove empty join */
3923 PDEBUG(DEBUG_EPOINT, "EPOINT(%d)d-join completely removed!\n");
3925 /* mixer must update */
3926 our_joinpbx->j_updatebridge = 1; /* update mixer flag */
3928 /* we send a retrieve to that endpoint */
3929 // mixer will update the hold-state of the join and send it to the endpoints is changes
3933 /* check if we have an external call
3934 * this is used to check for encryption ability
3936 int EndpointAppPBX::check_external(char **errstr, class Port **port)
3938 struct join_relation *relation;
3940 class JoinPBX *joinpbx;
3941 class Endpoint *epoint;
3943 /* some paranoia check */
3944 if (!ea_endpoint->ep_portlist)
3946 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we have no port.\n", ea_endpoint->ep_serial);
3947 *errstr = "No Call";
3950 if (!e_ext.number[0])
3952 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we are not internal extension.\n", ea_endpoint->ep_serial);
3953 *errstr = "No Call";
3957 /* check if we have a join with 2 parties */
3958 join = find_join_id(ea_endpoint->ep_join_id);
3961 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have currently no join.\n", ea_endpoint->ep_serial);
3962 *errstr = "No Call";
3965 if (join->j_type != JOIN_TYPE_PBX)
3967 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join is not a pbx join.\n", ea_endpoint->ep_serial);
3968 *errstr = "No PBX Call";
3971 joinpbx = (class JoinPBX *)join;
3972 relation = joinpbx->j_relation;
3975 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no relation.\n", ea_endpoint->ep_serial);
3976 *errstr = "No Call";
3979 if (!relation->next)
3981 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd relation.\n", ea_endpoint->ep_serial);
3982 *errstr = "No Call";
3985 if (relation->next->next)
3987 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has more than two relations.\n", ea_endpoint->ep_serial);
3988 *errstr = "Err: Conference";
3991 if (relation->epoint_id == ea_endpoint->ep_serial)
3993 relation = relation->next;
3994 if (relation->epoint_id == ea_endpoint->ep_serial)
3996 PERROR("EPOINT(%d) SOFTWARE ERROR: both join relations are related to our endpoint.\n", ea_endpoint->ep_serial);
3997 *errstr = "Software Error";
4002 /* check remote port for external call */
4003 epoint = find_epoint_id(relation->epoint_id);
4006 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd endpoint.\n", ea_endpoint->ep_serial);
4007 *errstr = "No Call";
4010 if (!epoint->ep_portlist)
4012 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not port.\n", ea_endpoint->ep_serial);
4013 *errstr = "No Call";
4016 *port = find_port_id(epoint->ep_portlist->port_id);
4019 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has an none existing port.\n", ea_endpoint->ep_serial);
4020 *errstr = "No Call";
4023 if (((*port)->p_type&PORT_CLASS_mISDN_MASK)!=PORT_CLASS_mISDN_DSS1) /* port is not external isdn */
4025 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not an external port.\n", ea_endpoint->ep_serial);
4026 *errstr = "No Ext Call";
4029 if ((*port)->p_state != PORT_STATE_CONNECT)
4031 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint's port is not in connected state.\n", ea_endpoint->ep_serial);
4032 *errstr = "No Ext Connect";
4038 void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsigned long port_id, int dir)
4040 char *logtext = "unknown";
4043 switch(message_type)
4046 trace_header("SETUP", dir);
4047 if (dir == DIRECTION_OUT)
4048 add_trace("to", NULL, "CH(%lu)", port_id);
4049 if (dir == DIRECTION_IN)
4050 add_trace("from", NULL, "CH(%lu)", port_id);
4051 if (param->setup.callerinfo.extension[0])
4052 add_trace("extension", NULL, "%s", param->setup.callerinfo.extension);
4053 add_trace("caller id", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype, options.national, options.international));
4054 switch(param->setup.callerinfo.present)
4056 case INFO_PRESENT_RESTRICTED:
4057 add_trace("caller id", "present", "restricted");
4059 case INFO_PRESENT_ALLOWED:
4060 add_trace("caller id", "present", "allowed");
4063 add_trace("caller id", "present", "not available");
4065 if (param->setup.redirinfo.id[0])
4067 add_trace("redir'ing", "number", "%s", numberrize_callerinfo(param->setup.redirinfo.id, param->setup.redirinfo.ntype, options.national, options.international));
4068 switch(param->setup.redirinfo.present)
4070 case INFO_PRESENT_RESTRICTED:
4071 add_trace("redir'ing", "present", "restricted");
4073 case INFO_PRESENT_ALLOWED:
4074 add_trace("redir'ing", "present", "allowed");
4077 add_trace("redir'ing", "present", "not available");
4080 if (param->setup.dialinginfo.id[0])
4081 add_trace("dialing", NULL, "%s", param->setup.dialinginfo.id);
4085 case MESSAGE_OVERLAP:
4086 trace_header("SETUP ACKNOWLEDGE", dir);
4087 if (dir == DIRECTION_OUT)
4088 add_trace("to", NULL, "CH(%lu)", port_id);
4089 if (dir == DIRECTION_IN)
4090 add_trace("from", NULL, "CH(%lu)", port_id);
4094 case MESSAGE_PROCEEDING:
4095 trace_header("PROCEEDING", dir);
4096 if (dir == DIRECTION_OUT)
4097 add_trace("to", NULL, "CH(%lu)", port_id);
4098 if (dir == DIRECTION_IN)
4099 add_trace("from", NULL, "CH(%lu)", port_id);
4103 case MESSAGE_ALERTING:
4104 trace_header("ALERTING", dir);
4105 if (dir == DIRECTION_OUT)
4106 add_trace("to", NULL, "CH(%lu)", port_id);
4107 if (dir == DIRECTION_IN)
4108 add_trace("from", NULL, "CH(%lu)", port_id);
4112 case MESSAGE_CONNECT:
4113 trace_header("CONNECT", dir);
4114 if (dir == DIRECTION_OUT)
4115 add_trace("to", NULL, "CH(%lu)", port_id);
4116 if (dir == DIRECTION_IN)
4117 add_trace("from", NULL, "CH(%lu)", port_id);
4118 if (param->connectinfo.extension[0])
4119 add_trace("extension", NULL, "%s", param->connectinfo.extension);
4120 add_trace("connect id", "number", "%s", numberrize_callerinfo(param->connectinfo.id, param->connectinfo.ntype, options.national, options.international));
4121 switch(param->connectinfo.present)
4123 case INFO_PRESENT_RESTRICTED:
4124 add_trace("connect id", "present", "restricted");
4126 case INFO_PRESENT_ALLOWED:
4127 add_trace("connect id", "present", "allowed");
4130 add_trace("connect id", "present", "not available");
4135 case MESSAGE_DISCONNECT:
4136 case MESSAGE_RELEASE:
4137 if (message_type == MESSAGE_DISCONNECT)
4138 trace_header("DISCONNECT", dir);
4140 trace_header("RELEASE", dir);
4141 if (dir == DIRECTION_OUT)
4142 add_trace("to", NULL, "CH(%lu)", port_id);
4143 if (dir == DIRECTION_IN)
4144 add_trace("from", NULL, "CH(%lu)", port_id);
4145 add_trace("cause", "value", "%d", param->disconnectinfo.cause);
4146 switch(param->disconnectinfo.location)
4149 add_trace("cause", "location", "0-User");
4151 case LOCATION_PRIVATE_LOCAL:
4152 add_trace("cause", "location", "1-Local-PBX");
4154 case LOCATION_PUBLIC_LOCAL:
4155 add_trace("cause", "location", "2-Local-Exchange");
4157 case LOCATION_TRANSIT:
4158 add_trace("cause", "location", "3-Transit");
4160 case LOCATION_PUBLIC_REMOTE:
4161 add_trace("cause", "location", "4-Remote-Exchange");
4163 case LOCATION_PRIVATE_REMOTE:
4164 add_trace("cause", "location", "5-Remote-PBX");
4166 case LOCATION_INTERNATIONAL:
4167 add_trace("cause", "location", "7-International-Exchange");
4169 case LOCATION_BEYOND:
4170 add_trace("cause", "location", "10-Beyond-Interworking");
4173 add_trace("cause", "location", "%d", param->disconnectinfo.location);
4178 case MESSAGE_NOTIFY:
4179 switch(param->notifyinfo.notify)
4185 logtext = "USER_SUSPENDED";
4188 logtext = "BEARER_SERVICE_CHANGED";
4191 logtext = "USER_RESUMED";
4194 logtext = "CONFERENCE_ESTABLISHED";
4197 logtext = "CONFERENCE_DISCONNECTED";
4200 logtext = "OTHER_PARTY_ADDED";
4203 logtext = "ISOLATED";
4206 logtext = "REATTACHED";
4209 logtext = "OTHER_PARTY_ISOLATED";
4212 logtext = "OTHER_PARTY_REATTACHED";
4215 logtext = "OTHER_PARTY_SPLIT";
4218 logtext = "OTHER_PARTY_DISCONNECTED";
4221 logtext = "CONFERENCE_FLOATING";
4224 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
4227 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
4230 logtext = "CALL_IS_A_WAITING_CALL";
4233 logtext = "DIVERSION_ACTIVATED";
4236 logtext = "RESERVED_CT_1";
4239 logtext = "RESERVED_CT_2";
4242 logtext = "REVERSE_CHARGING";
4245 logtext = "REMOTE_HOLD";
4248 logtext = "REMOTE_RETRIEVAL";
4251 logtext = "CALL_IS_DIVERTING";
4254 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
4258 trace_header("NOTIFY", dir);
4259 if (dir == DIRECTION_OUT)
4260 add_trace("to", NULL, "CH(%lu)", port_id);
4261 if (dir == DIRECTION_IN)
4262 add_trace("from", NULL, "CH(%lu)", port_id);
4263 if (param->notifyinfo.notify)
4264 add_trace("indicator", NULL, "%s", logtext);
4265 if (param->notifyinfo.id[0])
4267 add_trace("redir'on", "number", "%s", numberrize_callerinfo(param->notifyinfo.id, param->notifyinfo.ntype, options.national, options.international));
4268 switch(param->notifyinfo.present)
4270 case INFO_PRESENT_RESTRICTED:
4271 add_trace("redir'on", "present", "restricted");
4273 case INFO_PRESENT_ALLOWED:
4274 add_trace("redir'on", "present", "allowed");
4277 add_trace("redir'on", "present", "not available");
4280 if (param->notifyinfo.display[0])
4281 add_trace("display", NULL, "%s", param->notifyinfo.display);
4285 case MESSAGE_INFORMATION:
4286 trace_header("INFORMATION", dir);
4287 if (dir == DIRECTION_OUT)
4288 add_trace("to", NULL, "CH(%lu)", port_id);
4289 if (dir == DIRECTION_IN)
4290 add_trace("from", NULL, "CH(%lu)", port_id);
4291 add_trace("dialing", NULL, "%s", param->information.id);
4295 case MESSAGE_FACILITY:
4296 trace_header("FACILITY", dir);
4297 if (dir == DIRECTION_OUT)
4298 add_trace("to", NULL, "CH(%lu)", port_id);
4299 if (dir == DIRECTION_IN)
4300 add_trace("from", NULL, "CH(%lu)", port_id);
4305 trace_header("TONE", dir);
4306 if (dir == DIRECTION_OUT)
4307 add_trace("to", NULL, "CH(%lu)", port_id);
4308 if (dir == DIRECTION_IN)
4309 add_trace("from", NULL, "CH(%lu)", port_id);
4310 if (param->tone.name[0])
4312 add_trace("directory", NULL, "%s", param->tone.dir[0]?param->tone.dir:"default");
4313 add_trace("name", NULL, "%s", param->tone.name);
4315 add_trace("off", NULL, NULL);
4319 case MESSAGE_SUSPEND:
4320 case MESSAGE_RESUME:
4321 if (message_type == MESSAGE_SUSPEND)
4322 trace_header("SUSPEND", dir);
4324 trace_header("RESUME", dir);
4325 if (dir == DIRECTION_OUT)
4326 add_trace("to", NULL, "CH(%lu)", port_id);
4327 if (dir == DIRECTION_IN)
4328 add_trace("from", NULL, "CH(%lu)", port_id);
4329 if (param->parkinfo.len)
4330 add_trace("length", NULL, "%d", param->parkinfo.len);
4335 case MESSAGE_BCHANNEL:
4336 trace_header("BCHANNEL", dir);
4337 switch(param->bchannel.type)
4339 case BCHANNEL_REQUEST:
4340 add_trace("type", NULL, "request");
4342 case BCHANNEL_ASSIGN:
4343 add_trace("type", NULL, "assign");
4345 case BCHANNEL_ASSIGN_ACK:
4346 add_trace("type", NULL, "assign_ack");
4348 case BCHANNEL_REMOVE:
4349 add_trace("type", NULL, "remove");
4351 case BCHANNEL_REMOVE_ACK:
4352 add_trace("type", NULL, "remove_ack");
4355 if (param->bchannel.addr)
4356 add_trace("address", NULL, "%x", param->bchannel.addr);
4362 PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message_type);
4366 void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cause, int location, char *display)
4368 struct lcr_msg *message;
4372 if (!portlist->port_id)
4375 if (!e_connectedmode)
4377 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT);
4378 message->param.disconnectinfo.cause = cause;
4379 message->param.disconnectinfo.location = location;
4381 SCPY(message->param.disconnectinfo.display, display);
4383 SCPY(message->param.disconnectinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4386 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
4388 SCPY(message->param.notifyinfo.display, display);
4390 SCPY(message->param.notifyinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4392 message_put(message);
4393 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);