1 /*****************************************************************************\
3 ** Linux Call Router **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
8 ** The EndpointAppPBX implements PBX4Linux **
10 \*****************************************************************************/
15 #include <sys/types.h>
23 class EndpointAppPBX *apppbx_first = NULL;
26 * EndpointAppPBX constructor
28 EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint, int origin) : EndpointApp(epoint, origin)
30 class EndpointAppPBX **apppointer;
32 /* add application to chain */
34 apppointer = &apppbx_first;
36 apppointer = &((*apppointer)->next);
40 memset(&e_ext, 0, sizeof(struct extension));
41 // *************** NOTE: also change value in read_extension() **************
42 e_ext.rights = 4; /* international */
43 e_ext.rx_gain = e_ext.tx_gain = 0;
44 e_state = EPOINT_STATE_IDLE;
45 e_ext.number[0] = '\0';
46 e_extension_interface[0] = '\0';
47 memset(&e_callerinfo, 0, sizeof(struct caller_info));
48 memset(&e_dialinginfo, 0, sizeof(struct dialing_info));
49 memset(&e_connectinfo, 0, sizeof(struct connect_info));
50 memset(&e_redirinfo, 0, sizeof(struct redir_info));
51 memset(&e_capainfo, 0, sizeof(struct capa_info));
54 e_ruleset = ruleset_main;
56 e_rule = e_ruleset->rule_first;
61 e_match_to_action = NULL;
63 e_extdialing = e_dialinginfo.id;
67 // e_join_tone[0] = e_hold_tone[0] = '\0';
68 e_join_pattern /*= e_hold_pattern*/ = 0;
71 e_adminid = 0; // will be set, if call was initiated via admin socket
76 e_cbdialing[0] = '\0';
79 memset(&e_callbackinfo, 0, sizeof(struct caller_info));
86 e_password_timeout = 0;
87 e_multipoint_cause = 0;
88 e_multipoint_location = 0;
89 e_dialing_queue[0] = '\0';
91 e_crypt_state = CM_ST_NULL;
92 e_crypt_keyengine_busy = 0;
93 e_crypt_info[0] = '\0';
96 e_tx_state = NOTIFY_STATE_ACTIVE;
97 e_rx_state = NOTIFY_STATE_ACTIVE;
98 e_join_cause = e_join_location = 0;
99 /*********************************
100 *********************************
101 ********* ATTENTION *************
102 *********************************
103 *********************************/
104 /* if you add new values, that must be initialized, also check if they must
105 * be initialized when doing callback
111 * EpointAppPBX destructor
113 EndpointAppPBX::~EndpointAppPBX(void)
115 class EndpointAppPBX *temp, **tempp;
119 tempp = &apppbx_first;
129 FATAL("Endpoint not in endpoint's list.\n");
136 * trace header for application
138 void EndpointAppPBX::trace_header(char *name, int direction)
142 char msgtext[sizeof(_trace.name)];
146 /* init trace with given values */
149 numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype),
153 ea_endpoint->ep_serial,
160 /* set new endpoint state
162 void EndpointAppPBX::new_state(int state)
165 if (e_state != state)
167 trace_header("NEW STATE", DIRECTION_NONE);
168 add_trace("state", "old", "%s", state_name[e_state]);
169 add_trace("state", "new", "%s", state_name[state]);
177 /* release join and port (as specified)
179 void EndpointAppPBX::release(int release, int joinlocation, int joincause, int portlocation, int portcause)
181 struct port_list *portlist;
182 struct message *message;
185 /* message to test call */
186 admin_call_response(e_adminid, ADMIN_CALL_RELEASE, "", joincause, joinlocation, 0);
188 /* if a release is pending */
189 if (release==RELEASE_JOIN || release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY)
191 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): do pending release (joincause %d location %d)\n", ea_endpoint->ep_serial, joincause, joinlocation);
192 if (ea_endpoint->ep_join_id)
194 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_RELEASE);
195 message->param.disconnectinfo.cause = joincause;
196 message->param.disconnectinfo.location = joinlocation;
197 message_put(message);
198 ea_endpoint->ep_join_id = 0;
202 if (release != RELEASE_PORT_JOINONLY)
205 join_release(e_hold_id, ea_endpoint->ep_serial, 1, joinlocation, joincause);
210 if (release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY)
212 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release (portcause %d portlocation)\n", ea_endpoint->ep_serial, portcause, portlocation);
213 while((portlist = ea_endpoint->ep_portlist))
215 if (portlist->port_id)
217 SPRINT(cause, "cause_%02x", portcause);
218 set_tone(portlist, cause);
219 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
220 message->param.disconnectinfo.cause = portcause;
221 message->param.disconnectinfo.location = portlocation;
222 message_put(message);
223 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
225 ea_endpoint->free_portlist(portlist);
228 /* if callback is enabled, call back with the given caller id */
231 /* reset some stuff */
232 new_state(EPOINT_STATE_IDLE);
233 memset(&e_connectinfo, 0, sizeof(struct connect_info));
234 memset(&e_redirinfo, 0, sizeof(struct redir_info));
235 e_start = e_stop = 0;
236 e_ruleset = ruleset_main;
238 e_rule = e_ruleset->rule_first;
240 e_action_timeout = 0;
242 e_match_to_action = NULL;
244 e_extdialing = e_dialinginfo.id;
251 e_multipoint_cause = 0;
252 e_multipoint_location = 0;
253 e_dialing_queue[0] = '\0';
255 e_crypt_state = CM_ST_NULL;
256 e_crypt_keyengine_busy = 0;
257 e_crypt_info[0] = '\0';
261 e_tx_state = NOTIFY_STATE_ACTIVE;
262 e_rx_state = NOTIFY_STATE_ACTIVE;
263 e_join_cause = e_join_location = 0;
265 /* the caller info of the callback user */
266 memcpy(&e_callbackinfo, &e_callerinfo, sizeof(e_callbackinfo));
267 memset(&e_dialinginfo, 0, sizeof(e_dialinginfo));
268 /* create dialing by callerinfo */
269 if (e_ext.number[0] && e_extension_interface[0])
271 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to internal: %s interface %s\n", ea_endpoint->ep_serial, e_ext.number, e_extension_interface);
272 /* create callback to the current terminal */
273 SCPY(e_dialinginfo.id, e_ext.number);
274 SCPY(e_dialinginfo.interfaces, e_extension_interface);
275 e_dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
276 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
281 SCPY(e_dialinginfo.id, e_cbto);
284 /* numberrize caller id and use it to dial to the callback */
285 SCPY(e_dialinginfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype));
287 e_dialinginfo.itype = INFO_ITYPE_ISDN;
288 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
289 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to external: %s\n", ea_endpoint->ep_serial, e_dialinginfo.id);
294 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release of epoint itself.\n", ea_endpoint->ep_serial);
295 ea_endpoint->ep_use--; /* when e_lock is 0, the endpoint will be deleted */
301 /* cancel callerid if restricted, unless anon-ignore is enabled at extension or port is of type external (so called police gets caller id :)*/
302 void apply_callerid_restriction(struct extension *ext, char *id, int *ntype, int *present, int *screen, char *extension, char *name)
304 PDEBUG(DEBUG_EPOINT, "id='%s' ntype=%d present=%d screen=%d extension='%s' name='%s'\n", (id)?id:"NULL", (ntype)?*ntype:-1, (present)?*present:-1, (screen)?*screen:-1, (extension)?extension:"NULL", (name)?name:"NULL");
306 /* caller id is not restricted, so we do nothing */
307 if (*present != INFO_PRESENT_RESTRICTED)
310 /* only extensions are restricted */
314 /* if we enabled anonymouse ignore */
315 if (ext->anon_ignore)
318 /* else we remove the caller id */
322 *ntype = INFO_NTYPE_UNKNOWN;
324 // *screen = INFO_SCREEN_USER;
325 // maybe we should not make voip address anonymous
328 // maybe it's no fraud to present extension id
330 // extension[0] = '\0';
335 /* used display message to display callerid as available */
336 char *EndpointAppPBX::apply_callerid_display(char *id, int itype, int ntype, int present, int screen, char *extension, char *name)
338 static char display[81];
341 char *cid = numberrize_callerinfo(id, ntype);
343 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) id='%s' itype=%d ntype=%d present=%d screen=%d extension='%s' name='%s'\n", ea_endpoint->ep_serial, (id)?id:"NULL", itype, ntype, present, screen, (extension)?extension:"NULL", (name)?name:"NULL");
352 /* NOTE: is caller is is not available for this extesion, it has been removed by apply_callerid_restriction already */
354 /* internal extension's caller id */
355 if (extension[0] && e_ext.display_int)
358 SCAT(display, extension);
361 if (itype == INFO_ITYPE_VBOX)
362 SCAT(display, "(vbox)");
364 SCAT(display, "(int)");
367 /* external caller id */
368 if (!extension[0] && e_ext.display_ext)
374 if (present == INFO_PRESENT_RESTRICTED)
375 SCAT(display, "anonymous");
377 SCAT(display, "unknown");
384 /* display if callerid is anonymouse but available due anon-ignore */
385 if (e_ext.display_anon && present==INFO_PRESENT_RESTRICTED)
388 SCAT(display, "unknown");
391 SCAT(display, " anon");
394 /* display if callerid is anonymouse but available due anon-ignore */
395 if (e_ext.display_fake && screen==INFO_SCREEN_USER && present!=INFO_PRESENT_NULL)
401 if (present == INFO_PRESENT_RESTRICTED)
402 SCAT(display, "anonymous");
404 SCAT(display, "unknown");
409 SCAT(display, " fake");
413 if (name[0] && e_ext.display_name)
415 if (!display[0] && cid[0])
426 * uses the current state to notify activity
428 void EndpointAppPBX::notify_active(void)
430 struct port_list *portlist = ea_endpoint->ep_portlist;
431 struct message *message;
436 case NOTIFY_STATE_ACTIVE:
437 /* we are already active, so we don't do anything */
440 case NOTIFY_STATE_SUSPEND:
441 notify = INFO_NOTIFY_USER_RESUMED;
444 set_tone(portlist, NULL);
445 portlist = portlist->next;
447 portlist = ea_endpoint->ep_portlist;
450 case NOTIFY_STATE_HOLD:
451 notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
454 set_tone(portlist, NULL);
455 portlist = portlist->next;
457 portlist = ea_endpoint->ep_portlist;
460 case NOTIFY_STATE_CONFERENCE:
461 notify = INFO_NOTIFY_CONFERENCE_DISCONNECTED;
464 set_tone(portlist, NULL);
465 portlist = portlist->next;
467 portlist = ea_endpoint->ep_portlist;
471 PERROR("unknown e_tx_state = %d\n", e_tx_state);
477 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
478 message->param.notifyinfo.notify = notify;
479 message_put(message);
480 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
481 portlist = portlist->next;
487 * keypad functions during call. one example to use this is to put a call on hold or start a conference
489 void EndpointAppPBX::keypad_function(char digit)
492 /* we must be in a call, in order to send messages to the call */
493 if (e_ext.number[0] == '\0')
495 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) IGNORING keypad received not from extension.\n", ea_endpoint->ep_serial);
501 /* join conference */
503 if (ea_endpoint->ep_join_id == 0)
505 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad received during connect but not during a call.\n", ea_endpoint->ep_serial);
508 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join call with call on hold\n", ea_endpoint->ep_serial);
514 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) shared key encryption selected.\n", ea_endpoint->ep_serial);
518 /* crypt key-exchange */
520 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) key exchange encryption selected.\n", ea_endpoint->ep_serial);
526 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) encryption off selected.\n", ea_endpoint->ep_serial);
531 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) unsupported keypad digit '%c'.\n", ea_endpoint->ep_serial, digit);
536 /* set tone pattern for port */
537 void EndpointAppPBX::set_tone(struct port_list *portlist, char *tone)
539 struct message *message;
544 /* store for suspended processes */
548 if (e_join_pattern /* pattern are provided */
549 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_SETUP)
550 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_OVERLAP)
551 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_IN_PROCEEDING)
552 && !(e_ext.own_alerting && e_state == EPOINT_STATE_IN_ALERTING)
553 && !(e_ext.own_cause && e_state == EPOINT_STATE_IN_DISCONNECT)
554 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_SETUP)
555 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_OVERLAP)
556 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_OUT_PROCEEDING)
557 && !(e_ext.own_alerting && e_state == EPOINT_STATE_OUT_ALERTING)
558 && !(e_ext.own_cause && e_state == EPOINT_STATE_OUT_DISCONNECT)
559 && tone[0] && !!strncmp(tone,"crypt_*",6))
561 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) tone not provided since patterns are available\n", ea_endpoint->ep_serial);
567 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_TONE);
568 SCPY(message->param.tone.dir, e_ext.tones_dir[0]?e_ext.tones_dir:options.tones_dir);
569 SCPY(message->param.tone.name, tone);
570 message_put(message);
571 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
574 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port to notify tone.\n", ea_endpoint->ep_serial);
581 * hunts an mISDNport that is available for an outgoing call
582 * if no ifname was given, any interface that is not an extension
585 struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel)
587 struct interface *interface;
588 struct interface_port *ifport, *ifport_start;
589 struct select_channel *selchannel;
590 struct mISDNport *mISDNport;
593 interface = interface_first;
595 /* first find the given interface or, if not given, one with no extension */
600 /* check for given interface */
603 if (!strcasecmp(interface->name, ifname))
605 /* found explicit interface */
606 trace_header("CHANNEL SELECTION (found interface)", DIRECTION_NONE);
607 add_trace("interface", NULL, "%s", ifname);
614 if (!interface->extension)
616 /* found non extension */
617 trace_header("CHANNEL SELECTION (found non extension interface)", DIRECTION_NONE);
618 add_trace("interface", NULL, "%s", interface->name);
624 interface = interface->next;
628 /* see if interface has ports */
629 if (!interface->ifport)
632 trace_header("CHANNEL SELECTION (interface has no active ports, skipping)", DIRECTION_NONE);
633 add_trace("interface", NULL, "%s", interface->name);
635 interface = interface->next;
639 /* select port by algorithm */
640 ifport_start = interface->ifport;
642 if (interface->hunt == HUNT_ROUNDROBIN)
644 while(ifport_start->next && index<interface->hunt_next)
646 ifport_start = ifport_start->next;
649 trace_header("CHANNEL SELECTION (starting round-robin)", DIRECTION_NONE);
650 add_trace("port", NULL, "%d", ifport_start->portnum);
651 add_trace("position", NULL, "%d", index);
656 ifport = ifport_start;
659 /* see if port is available */
660 if (!ifport->mISDNport)
662 trace_header("CHANNEL SELECTION (port not available, skipping)", DIRECTION_NONE);
663 add_trace("port", NULL, "%d", ifport->portnum);
664 add_trace("position", NULL, "%d", index);
668 mISDNport = ifport->mISDNport;
670 /* see if port is administratively blocked */
673 trace_header("CHANNEL SELECTION (port blocked by admin, skipping)", DIRECTION_NONE);
674 add_trace("port", NULL, "%d", ifport->portnum);
675 add_trace("position", NULL, "%d", index);
680 /* see if link is up on PTP*/
681 if (mISDNport->ptp && !mISDNport->l2link)
683 trace_header("CHANNEL SELECTION (port is ptp with layer 2 down, skipping)", DIRECTION_NONE);
684 add_trace("port", NULL, "%d", ifport->portnum);
685 add_trace("position", NULL, "%d", index);
690 /* check for channel form selection list */
692 selchannel = ifport->out_channel;
695 switch(selchannel->channel)
697 case CHANNEL_FREE: /* free channel */
698 if (mISDNport->b_reserved >= mISDNport->b_num)
699 break; /* all channel in use or reserverd */
702 while(i < mISDNport->b_num)
704 if (mISDNport->b_port[i] == NULL)
706 *channel = i+1+(i>=15);
707 trace_header("CHANNEL SELECTION (selecting free channel)", DIRECTION_NONE);
708 add_trace("port", NULL, "%d", ifport->portnum);
709 add_trace("position", NULL, "%d", index);
710 add_trace("channel", NULL, "%d", *channel);
718 trace_header("CHANNEL SELECTION (no channel is 'free')", DIRECTION_NONE);
719 add_trace("port", NULL, "%d", ifport->portnum);
720 add_trace("position", NULL, "%d", index);
724 case CHANNEL_ANY: /* don't ask for channel */
725 if (mISDNport->b_reserved >= mISDNport->b_num)
727 trace_header("CHANNEL SELECTION (cannot ask for 'any' channel, all reserved)", DIRECTION_NONE);
728 add_trace("port", NULL, "%d", ifport->portnum);
729 add_trace("position", NULL, "%d", index);
730 add_trace("total", NULL, "%d", mISDNport->b_num);
731 add_trace("reserved", NULL, "%d", mISDNport->b_reserved);
733 break; /* all channel in use or reserverd */
735 trace_header("CHANNEL SELECTION (using 'any' channel)", DIRECTION_NONE);
736 add_trace("port", NULL, "%d", ifport->portnum);
737 add_trace("position", NULL, "%d", index);
739 *channel = CHANNEL_ANY;
742 case CHANNEL_NO: /* call waiting */
743 trace_header("CHANNEL SELECTION (using 'no' channel, call-waiting)", DIRECTION_NONE);
744 add_trace("port", NULL, "%d", ifport->portnum);
745 add_trace("position", NULL, "%d", index);
747 *channel = CHANNEL_NO;
751 if (selchannel->channel<1 || selchannel->channel==16)
753 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
754 add_trace("port", NULL, "%d", ifport->portnum);
755 add_trace("position", NULL, "%d", index);
756 add_trace("channel", NULL, "%d", selchannel->channel);
758 break; /* invalid channels */
760 i = selchannel->channel-1-(selchannel->channel>=17);
761 if (i >= mISDNport->b_num)
763 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
764 add_trace("port", NULL, "%d", ifport->portnum);
765 add_trace("position", NULL, "%d", index);
766 add_trace("channel", NULL, "%d", selchannel->channel);
767 add_trace("channels", NULL, "%d", mISDNport->b_num);
769 break; /* channel not in port */
771 if (mISDNport->b_port[i] == NULL)
773 *channel = selchannel->channel;
774 trace_header("CHANNEL SELECTION (selecting given channel)", DIRECTION_NONE);
775 add_trace("port", NULL, "%d", ifport->portnum);
776 add_trace("position", NULL, "%d", index);
777 add_trace("channel", NULL, "%d", *channel);
784 break; /* found channel */
785 selchannel = selchannel->next;
788 /* if channel was found, return mISDNport and channel */
791 /* setting next port to start next time */
792 if (interface->hunt == HUNT_ROUNDROBIN)
797 interface->hunt_next = index;
803 trace_header("CHANNEL SELECTION (skipping, no channel found)", DIRECTION_NONE);
804 add_trace("port", NULL, "%d", ifport->portnum);
805 add_trace("position", NULL, "%d", index);
809 /* go next port, until all ports are checked */
811 ifport = ifport->next;
815 ifport = interface->ifport;
817 if (ifport != ifport_start)
820 return(NULL); /* no port found */
823 /* outgoing setup to port(s)
824 * ports will be created and a setup is sent if everything is ok. otherwhise
825 * the endpoint is destroyed.
827 void EndpointAppPBX::out_setup(void)
829 struct dialing_info dialinginfo;
831 // class pdss1 *pdss1;
832 struct port_list *portlist;
833 struct message *message;
835 int cause = CAUSE_RESSOURCEUNAVAIL;
838 struct mISDNport *mISDNport;
841 class EndpointAppPBX *atemp;
842 // char allowed_ports[256];
844 char ifname[sizeof(e_ext.interfaces)],
846 struct port_settings port_settings;
850 /* create settings for creating port */
851 memset(&port_settings, 0, sizeof(port_settings));
853 SCPY(port_settings.tones_dir, e_ext.tones_dir);
855 SCPY(port_settings.tones_dir, options.tones_dir);
856 port_settings.no_seconds = e_ext.no_seconds;
858 /* NOTE: currently the try_card feature is not supported. it should be used later to try another card, if the outgoing call fails on one port */
860 /* check what dialinginfo.itype we got */
861 switch(e_dialinginfo.itype)
863 /* *********************** call to extension or vbox */
864 case INFO_ITYPE_ISDN_EXTENSION:
865 /* check if we deny incoming calls when we use an extension */
866 if (e_ext.noknocking)
868 atemp = apppbx_first;
872 if (!strcmp(atemp->e_ext.number, e_ext.number))
878 PERROR("EPOINT(%d) noknocking and currently a call\n", ea_endpoint->ep_serial);
879 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYSPE_ join, port */
880 return; /* must exit here */
883 /* FALL THROUGH !!!! */
884 case INFO_ITYPE_VBOX:
885 /* get dialed extension's info */
886 // SCPY(exten, e_dialinginfo.id);
887 // if (strchr(exten, ','))
888 // *strchr(exten, ',') = '\0';
889 // if (!read_extension(&e_ext, exten))
890 if (!read_extension(&e_ext, e_dialinginfo.id))
892 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) extension %s not configured\n", ea_endpoint->ep_serial, e_dialinginfo.id);
893 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
894 return; /* must exit here */
897 if (e_dialinginfo.itype == INFO_ITYPE_VBOX)
899 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing directly to VBOX\n", ea_endpoint->ep_serial);
904 /* string from unconditional call forward (cfu) */
908 /* present to forwarded party */
909 if (e_ext.anon_ignore && e_callerinfo.id[0])
911 e_callerinfo.present = INFO_PRESENT_ALLOWED;
913 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
917 /* string from busy call forward (cfb) */
921 class EndpointAppPBX *checkapp = apppbx_first;
924 if (checkapp != this) /* any other endpoint except our own */
926 if (!strcmp(checkapp->e_ext.number, e_ext.number))
928 /* present to forwarded party */
929 if (e_ext.anon_ignore && e_callerinfo.id[0])
931 e_callerinfo.present = INFO_PRESENT_ALLOWED;
933 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
937 checkapp = checkapp->next;
941 /* string from no-response call forward (cfnr) */
945 /* when cfnr is done, out_setup() will setup the call */
948 /* present to forwarded party */
949 if (e_ext.anon_ignore && e_callerinfo.id[0])
951 e_callerinfo.present = INFO_PRESENT_ALLOWED;
955 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
957 e_cfnr_release = now + e_ext.cfnr_delay;
958 e_cfnr_call = now + e_ext.cfnr_delay + 1; /* call one second after release */
959 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) setting time for call-forward-busy to %s with delay %ld.\n", ea_endpoint->ep_serial, e_ext.cfnr, e_ext.cfnr_delay);
963 /* call to all internal interfaces */
964 p = e_ext.interfaces;
965 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) generating multiple joins for extension %s to interfaces %s\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
969 while(*p!=',' && *p!='\0')
974 /* found interface */
975 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
976 /* hunt for mISDNport and create Port */
977 mISDNport = hunt_port(ifname, &channel);
980 trace_header("INTERFACE (not found or busy)", DIRECTION_NONE);
981 add_trace("interface", NULL, "%s", ifname);
985 /* creating INTERNAL port */
986 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
987 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force);
989 FATAL("No memory for DSS1 Port instance\n");
990 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
991 memset(&dialinginfo, 0, sizeof(dialinginfo));
992 SCPY(dialinginfo.id, e_dialinginfo.id);
993 dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
994 dialinginfo.ntype = e_dialinginfo.ntype;
995 /* create port_list relation */
996 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
999 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1001 goto check_anycall_intern;
1003 /* directory.list */
1004 if (e_callerinfo.id[0] && (e_ext.centrex || e_ext.display_name))
1006 dirname = parse_directory(e_callerinfo.id, e_callerinfo.ntype);
1008 SCPY(e_callerinfo.name, dirname);
1010 // dss1 = (class Pdss1 *)port;
1012 //printf("INTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1013 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1014 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1015 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1016 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1017 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1018 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1019 //terminal if (e_dialinginfo.id)
1020 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1021 /* handle restricted caller ids */
1022 apply_callerid_restriction(&e_ext, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
1023 apply_callerid_restriction(&e_ext, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, 0, message->param.setup.redirinfo.extension, NULL);
1024 /* display callerid if desired for extension */
1025 SCPY(message->param.setup.callerinfo.display, apply_callerid_display(message->param.setup.callerinfo.id, message->param.setup.callerinfo.itype, message->param.setup.callerinfo.ntype, message->param.setup.callerinfo.present, message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name));
1026 //printf("\n\ndisplay = %s\n\n\n",message->param.setup.callerinfo.display);
1027 /* use cnip, if enabld */
1029 message->param.setup.callerinfo.name[0] = '\0';
1030 /* screen clip if prefix is required */
1031 if (message->param.setup.callerinfo.id[0] && e_ext.clip_prefix[0])
1033 SCPY(message->param.setup.callerinfo.id, e_ext.clip_prefix);
1034 SCAT(message->param.setup.callerinfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype));
1035 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1037 /* use internal caller id */
1038 if (e_callerinfo.extension[0] && (message->param.setup.callerinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
1040 SCPY(message->param.setup.callerinfo.id, e_callerinfo.extension);
1041 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1043 message_put(message);
1044 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1048 /* string from parallel call forward (cfp) */
1052 if (e_ext.anon_ignore && e_callerinfo.id[0])
1054 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1058 vbox_only: /* entry point for answering machine only */
1059 cfu_only: /* entry point for cfu */
1060 cfb_only: /* entry point for cfb */
1061 cfnr_only: /* entry point for cfnr */
1062 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call extension %s for external destiantion(s) '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
1067 /* only if vbox should be dialed, and terminal is given */
1068 if (!strcmp(p, "vbox") && e_ext.number[0])
1070 /* go to the end of p */
1073 /* answering vbox call */
1074 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) answering machine\n", ea_endpoint->ep_serial);
1076 if (!(port = new VBoxPort(PORT_TYPE_VBOX_OUT, &port_settings)))
1077 FATAL("No memory for VBOX Port instance\n");
1078 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocated port %s\n", ea_endpoint->ep_serial, port->p_name);
1079 UCPY(cfp, e_ext.number); /* cfp or any other direct forward/vbox */
1083 while(*p!=',' && *p!='\0')
1088 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cfp external %s\n", ea_endpoint->ep_serial, cfp);
1089 /* hunt for mISDNport and create Port */
1090 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1093 /* creating EXTERNAL port*/
1094 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1095 if (!(port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force)))
1096 FATAL("No memory for DSS1 Port instance\n");
1097 earlyb = mISDNport->earlyb;
1101 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1102 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1108 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port found or created, which is idle.\n", ea_endpoint->ep_serial);
1109 goto check_anycall_intern;
1111 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found or created port %s\n", ea_endpoint->ep_serial, port->p_name);
1112 memset(&dialinginfo, 0, sizeof(dialinginfo));
1113 SCPY(dialinginfo.id, cfp);
1114 dialinginfo.itype = INFO_ITYPE_ISDN;
1115 dialinginfo.ntype = e_dialinginfo.ntype;
1116 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
1119 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1121 goto check_anycall_intern;
1123 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1124 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1125 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1126 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1127 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1128 /* if clip is hidden */
1129 if (e_ext.clip==CLIP_HIDE && port->p_type!=PORT_TYPE_VBOX_OUT)
1131 SCPY(message->param.setup.callerinfo.id, e_ext.callerid);
1132 SCPY(message->param.setup.callerinfo.extension, e_ext.number);
1133 message->param.setup.callerinfo.ntype = e_ext.callerid_type;
1134 message->param.setup.callerinfo.present = e_ext.callerid_present;
1136 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1137 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1138 //terminal if (e_dialinginfo.id)
1139 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1140 /* handle restricted caller ids */
1141 apply_callerid_restriction(&e_ext, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
1142 apply_callerid_restriction(&e_ext, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, 0, message->param.setup.redirinfo.extension, NULL);
1143 /* display callerid if desired for extension */
1144 SCPY(message->param.setup.callerinfo.display, apply_callerid_display(message->param.setup.callerinfo.id, message->param.setup.callerinfo.itype, message->param.setup.callerinfo.ntype, message->param.setup.callerinfo.present, message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name));
1145 message_put(message);
1146 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1150 check_anycall_intern:
1151 /* now we have all ports created */
1154 trace_header("INTERFACE (no extension's interface)", DIRECTION_NONE);
1156 if (!ea_endpoint->ep_join_id)
1158 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1159 return; /* must exit here */
1163 /* *********************** external call */
1165 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id);
1166 /* call to extenal interfaces */
1167 p = e_dialinginfo.id;
1171 while(*p!=',' && *p!='\0')
1172 SCCAT(number, *p++);
1176 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to number '%s' interface '%s'\n", ea_endpoint->ep_serial, number, e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1177 /* hunt for mISDNport and create Port */
1178 /* hunt for mISDNport and create Port */
1179 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1182 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1183 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1185 goto check_anycall_extern;
1187 /* creating EXTERNAL port*/
1188 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1189 if (!(port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force)))
1190 FATAL("No memory for DSS1 Port instance\n");
1191 earlyb = mISDNport->earlyb;
1192 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
1193 memset(&dialinginfo, 0, sizeof(dialinginfo));
1194 SCPY(dialinginfo.id, number);
1195 dialinginfo.itype = INFO_ITYPE_ISDN;
1196 dialinginfo.ntype = e_dialinginfo.ntype;
1197 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
1200 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1202 goto check_anycall_extern;
1204 // dss1 = (class Pdss1 *)port;
1205 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1206 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1207 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1208 SCPY(message->param.setup.dialinginfo.id, number);
1209 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1210 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1211 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1212 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1213 //terminal if (e_dialinginfo.id)
1214 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1215 /* handle restricted caller ids */
1216 apply_callerid_restriction(&e_ext, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
1217 apply_callerid_restriction(&e_ext, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, 0, message->param.setup.redirinfo.extension, NULL);
1218 /* display callerid if desired for extension */
1219 SCPY(message->param.setup.callerinfo.display, apply_callerid_display(message->param.setup.callerinfo.id, message->param.setup.callerinfo.itype, message->param.setup.callerinfo.ntype, message->param.setup.callerinfo.present, message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name));
1220 message_put(message);
1221 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1225 check_anycall_extern:
1226 /* now we have all ports created */
1229 trace_header("INTERFACE (no free ports found)", DIRECTION_NONE);
1231 if (!ea_endpoint->ep_join_id)
1233 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1234 return; /* must exit here */
1242 /* handler for endpoint
1246 int EndpointAppPBX::handler(void)
1248 if (e_crypt_state!=CM_ST_NULL)
1253 /* process answering machine (play) handling */
1256 if (e_action->index == ACTION_VBOX_PLAY)
1259 /* process action timeout */
1260 if (e_action_timeout)
1261 if (now_d >= e_action_timeout)
1263 if (e_state!=EPOINT_STATE_CONNECT)
1266 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current action timed out.\n", ea_endpoint->ep_serial);
1267 e_multipoint_cause = 0;
1268 e_multipoint_location = 0;
1269 new_state(EPOINT_STATE_IN_OVERLAP);
1272 return(1); /* we must exit, because our endpoint might be gone */
1274 e_action_timeout = 0;
1277 /* process action timeout */
1278 if (e_match_timeout)
1279 if (now_d >= e_match_timeout)
1282 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we got a match timeout.\n", ea_endpoint->ep_serial);
1284 return(1); /* we must exit, because our endpoint might be gone */
1289 /* process redialing (epoint redials to port) */
1292 if (now_d >= e_redial)
1295 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial.\n", ea_endpoint->ep_serial);
1297 new_state(EPOINT_STATE_OUT_SETUP);
1298 /* call special setup routine */
1305 /* process powerdialing (epoint redials to epoint) */
1306 if (e_powerdialing > 0)
1308 if (now_d >= e_powerdialing)
1310 e_powerdialing = -1; /* leave power dialing on */
1311 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial of powerdial.\n", ea_endpoint->ep_serial);
1314 e_ruleset = ruleset_main;
1316 e_rule = e_ruleset->rule_first;
1318 new_state(EPOINT_STATE_IN_OVERLAP);
1324 /* process call forward no response */
1327 struct port_list *portlist;
1328 struct message *message;
1330 if (now >= e_cfnr_release)
1332 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-no-response time has expired, hanging up.\n", ea_endpoint->ep_serial);
1335 /* release all ports */
1336 while((portlist = ea_endpoint->ep_portlist))
1338 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1339 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
1340 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1341 message_put(message);
1342 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1343 ea_endpoint->free_portlist(portlist);
1346 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1347 message->param.audiopath = CHANNEL_STATE_HOLD;
1348 message_put(message);
1349 /* indicate no patterns */
1350 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1351 message_put(message);
1352 /* set setup state, since we have no response from the new join */
1353 new_state(EPOINT_STATE_OUT_SETUP);
1358 if (now >= e_cfnr_call)
1360 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-busy time has expired, calling the forwarded number: %s.\n", ea_endpoint->ep_serial, e_ext.cfnr);
1366 /* handle connection to user */
1367 if (e_state == EPOINT_STATE_IDLE)
1369 /* epoint is idle, check callback */
1371 if (now_d >= e_callback)
1373 e_callback = 0; /* done with callback */
1374 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting callback.\n", ea_endpoint->ep_serial);
1375 new_state(EPOINT_STATE_OUT_SETUP);
1381 /* check for password timeout */
1383 if (e_action->index==ACTION_PASSWORD || e_action->index==ACTION_PASSWORD_WRITE)
1385 struct port_list *portlist;
1387 if (now >= e_password_timeout)
1389 e_ruleset = ruleset_main;
1391 e_rule = e_ruleset->rule_first;
1393 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) password timeout %s\n", ea_endpoint->ep_serial, e_extdialing);
1394 trace_header("PASSWORD timeout", DIRECTION_NONE);
1396 e_connectedmode = 0;
1398 new_state(EPOINT_STATE_OUT_DISCONNECT);
1399 portlist = ea_endpoint->ep_portlist;
1402 message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
1403 set_tone(portlist, "cause_10");
1413 /* doing a hookflash */
1414 void EndpointAppPBX::hookflash(void)
1418 /* be sure that we are active */
1420 e_tx_state = NOTIFY_STATE_ACTIVE;
1422 trace_header("HOOKFLASH DTMF", DIRECTION_NONE);
1424 if (ea_endpoint->ep_use > 1)
1426 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot hooflash while child process is running.\n", ea_endpoint->ep_serial);
1429 /* dialtone after pressing the hash key */
1430 process_hangup(e_join_cause, e_join_location);
1431 e_multipoint_cause = 0;
1432 e_multipoint_location = 0;
1433 port = find_port_id(ea_endpoint->ep_portlist->port_id);
1436 port->set_echotest(0);
1438 if (ea_endpoint->ep_join_id)
1440 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1442 e_ruleset = ruleset_main;
1444 e_rule = e_ruleset->rule_first;
1446 new_state(EPOINT_STATE_IN_OVERLAP);
1447 e_connectedmode = 1;
1448 SCPY(e_dialinginfo.id, e_ext.prefix);
1449 e_extdialing = e_dialinginfo.id;
1451 if (e_dialinginfo.id[0])
1453 set_tone(ea_endpoint->ep_portlist, "dialing");
1457 set_tone(ea_endpoint->ep_portlist, "dialpbx");
1464 /* messages from port
1466 /* port MESSAGE_SETUP */
1467 void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, union parameter *param)
1469 struct message *message;
1471 int writeext; /* flags need to write extension after modification */
1473 struct interface *interface;
1475 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1477 portlist->port_type = param->setup.port_type;
1478 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
1479 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
1480 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
1481 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
1482 e_dtmf = param->setup.dtmf;
1483 /* screen incoming caller id */
1484 interface = interface_first;
1487 if (!strcmp(e_callerinfo.interface, interface->name))
1491 interface = interface->next;
1494 do_screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface);
1496 /* process extension */
1497 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1499 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is extension\n", ea_endpoint->ep_serial);
1500 /* port makes call from extension */
1501 SCPY(e_callerinfo.extension, e_callerinfo.id);
1502 SCPY(e_ext.number, e_callerinfo.extension);
1503 SCPY(e_extension_interface, e_callerinfo.interface);
1506 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is external or voip\n", ea_endpoint->ep_serial);
1509 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1511 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1513 /* get extension's info about caller */
1514 if (!read_extension(&e_ext, e_ext.number))
1516 /* extension doesn't exist */
1517 trace_header("EXTENSION (not created)", DIRECTION_IN);
1518 add_trace("extension", NULL, "%s", e_ext.number);
1520 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
1521 new_state(EPOINT_STATE_OUT_DISCONNECT);
1522 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
1523 e_ext.number[0] = '\0'; /* no terminal */
1528 /* put prefix (next) in front of e_dialinginfo.id */
1531 SPRINT(buffer, "%s%s", e_ext.next, e_dialinginfo.id);
1532 SCPY(e_dialinginfo.id, buffer);
1533 e_ext.next[0] = '\0';
1535 } else if (e_ext.prefix[0])
1537 SPRINT(buffer, "%s%s", e_ext.prefix, e_dialinginfo.id);
1538 SCPY(e_dialinginfo.id, buffer);
1541 /* screen caller id by extension's config */
1542 e_callerinfo.screen = INFO_SCREEN_NETWORK;
1544 SCPY(e_callerinfo.name, e_ext.name);
1545 /* use caller id (or if exist: id_next_call) for this call */
1546 if (e_ext.id_next_call_present >= 0)
1548 SCPY(e_callerinfo.id, e_ext.id_next_call);
1549 /* if we restrict the pesentation */
1550 if (e_ext.id_next_call_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1551 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1552 else e_callerinfo.present = e_ext.id_next_call_present;
1553 e_callerinfo.ntype = e_ext.id_next_call_type;
1554 e_ext.id_next_call_present = -1;
1558 SCPY(e_callerinfo.id, e_ext.callerid);
1559 /* if we restrict the pesentation */
1560 if (e_ext.callerid_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1561 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1562 else e_callerinfo.present = e_ext.callerid_present;
1563 e_callerinfo.ntype = e_ext.callerid_type;
1566 /* extension is written */
1568 write_extension(&e_ext, e_ext.number);
1570 /* set volume of rx and tx */
1571 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1572 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
1574 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
1575 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
1576 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
1577 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
1578 message_put(message);
1581 /* start recording if enabled */
1582 if (e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO))
1584 /* check if we are a terminal */
1585 if (e_ext.number[0] == '\0')
1586 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
1589 port = find_port_id(portlist->port_id);
1591 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
1596 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from external port\n", ea_endpoint->ep_serial);
1597 /* no terminal identification */
1598 e_ext.number[0] = '\0';
1599 e_extension_interface[0] = '\0';
1600 memset(&e_ext, 0, sizeof(e_ext));
1601 e_ext.rights = 4; /* right to dial internat */
1605 e_ruleset = ruleset_main;
1607 e_rule = e_ruleset->rule_first;
1609 e_extdialing = e_dialinginfo.id;
1610 new_state(EPOINT_STATE_IN_SETUP);
1611 if (e_dialinginfo.id[0])
1613 set_tone(portlist, "dialing");
1616 if (e_ext.number[0])
1617 set_tone(portlist, "dialpbx");
1619 set_tone(portlist, "dialtone");
1622 if (e_state == EPOINT_STATE_IN_SETUP)
1624 /* request MORE info, if not already at higher state */
1625 new_state(EPOINT_STATE_IN_OVERLAP);
1626 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_OVERLAP);
1627 message_put(message);
1628 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1632 /* port MESSAGE_INFORMATION */
1633 void EndpointAppPBX::port_information(struct port_list *portlist, int message_type, union parameter *param)
1635 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1639 /* turn off dtmf detection, in case dtmf is sent with keypad information */
1642 trace_header("DTMF (disabling due to keypad)", DIRECTION_IN);
1647 /* if vbox_play is done, the information are just used as they come */
1649 if (e_action->index == ACTION_VBOX_PLAY)
1651 /* concat dialing string */
1652 SCAT(e_dialinginfo.id, param->information.id);
1657 /* keypad when disconnect but in connected mode */
1658 if (e_state==EPOINT_STATE_OUT_DISCONNECT && e_connectedmode)
1660 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received after disconnect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1661 /* processing keypad function */
1662 if (param->information.id[0] == '0')
1669 /* keypad when connected */
1670 if (e_state == EPOINT_STATE_CONNECT)
1674 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1675 /* processing keypad function */
1676 if (param->information.id[0] == '0')
1680 if (param->information.id[0])
1681 keypad_function(param->information.id[0]);
1684 if (e_ext.number[0])
1685 trace_header("KEYPAD (not enabled by extension's settings)", DIRECTION_IN);
1687 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1692 if (e_state != EPOINT_STATE_IN_OVERLAP)
1694 if (e_ext.number[0])
1695 trace_header("KEYPAD (ignored, not connected and not dialing)", DIRECTION_IN);
1697 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1701 if (!param->information.id[0])
1703 if (e_dialinginfo.id[0]=='\0' && !e_action)
1705 set_tone(portlist, "dialing");
1708 if (e_action->index==ACTION_OUTDIAL
1709 || e_action->index==ACTION_EXTERNAL)
1712 set_tone(portlist, "dialing");
1713 else if (!e_extdialing[0])
1714 set_tone(portlist, "dialing");
1716 /* concat dialing string */
1717 SCAT(e_dialinginfo.id, param->information.id);
1721 /* port MESSAGE_DTMF */
1722 void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
1724 /* only if dtmf detection is enabled */
1727 trace_header("DTMF (disabled)", DIRECTION_IN);
1731 trace_header("DTMF", DIRECTION_IN);
1732 add_trace("digit", NULL, "%c", param->dtmf);
1736 NOTE: vbox is now handled due to overlap state
1737 /* if vbox_play is done, the dtmf digits are just used as they come */
1739 if (e_action->index == ACTION_VBOX_PLAY)
1741 /* concat dialing string */
1742 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id))
1744 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1745 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1748 /* continue to process *X# sequences */
1752 /* check for *X# sequence */
1753 if (e_state == EPOINT_STATE_CONNECT)
1755 if (e_dtmf_time+3 < now)
1757 /* the last digit was too far in the past to be a sequence */
1758 if (param->dtmf == '*')
1759 /* only start is allowed in the sequence */
1765 /* we have a sequence of digits, see what we got */
1766 if (param->dtmf == '*')
1768 else if (param->dtmf>='0' && param->dtmf<='9')
1770 /* we need to have a star before we receive the digit of the sequence */
1771 if (e_dtmf_last == '*')
1772 e_dtmf_last = param->dtmf;
1773 } else if (param->dtmf == '#')
1776 if (e_dtmf_last>='0' && e_dtmf_last<='9')
1778 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf sequence *%c# detected.\n", ea_endpoint->ep_serial, e_dtmf_last);
1779 if (e_dtmf_last == '0')
1784 /* processing keypad function */
1786 keypad_function(e_dtmf_last);
1792 /* set last time of dtmf */
1797 /* check for ## hookflash during dialing */
1799 if (e_action->index==ACTION_PASSWORD
1800 || e_action->index==ACTION_PASSWORD_WRITE)
1802 if (param->dtmf=='#') /* current digit is '#' */
1804 if (e_state==EPOINT_STATE_IN_DISCONNECT
1805 || (e_state!=EPOINT_STATE_CONNECT && e_dtmf_time+3>=now && e_dtmf_last=='#')) /* when disconnected, just #. when dialing, ##. */
1822 /* dialing using dtmf digit */
1823 if (e_state==EPOINT_STATE_IN_OVERLAP)// && e_state==e_connectedmode)
1825 if (e_dialinginfo.id[0]=='\0' && !e_action)
1827 set_tone(portlist, "dialing");
1829 /* concat dialing string */
1830 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id))
1832 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1833 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1839 /* port MESSAGE_CRYPT */
1840 void EndpointAppPBX::port_crypt(struct port_list *portlist, int message_type, union parameter *param)
1842 /* send crypt response to cryptman */
1843 if (param->crypt.type == CR_MESSAGE_IND)
1844 cryptman_msg2man(param->crypt.data, param->crypt.len);
1846 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
1849 /* port MESSAGE_OVERLAP */
1850 void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, union parameter *param)
1852 struct message *message;
1854 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1856 /* signal to call tool */
1857 admin_call_response(e_adminid, ADMIN_CALL_SETUP_ACK, "", 0, 0, 0);
1859 if (e_dialing_queue[0] && portlist)
1861 /* send what we have not dialed yet, because we had no setup complete */
1862 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing pending digits: '%s'\n", ea_endpoint->ep_serial, e_dialing_queue);
1863 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
1864 SCPY(message->param.information.id, e_dialing_queue);
1865 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
1866 message_put(message);
1867 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
1868 e_dialing_queue[0] = '\0';
1870 /* check if pattern is available */
1871 if (!ea_endpoint->ep_portlist->next && portlist->early_b) /* one port_list relation and tones available */
1873 /* indicate patterns */
1874 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1875 message_put(message);
1877 /* connect audio, if not already */
1878 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1879 message->param.audiopath = CHANNEL_STATE_CONNECT;
1880 message_put(message);
1883 /* indicate no patterns */
1884 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1885 message_put(message);
1887 /* disconnect audio, if not already */
1888 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1889 message->param.audiopath = CHANNEL_STATE_HOLD;
1890 message_put(message);
1892 new_state(EPOINT_STATE_OUT_OVERLAP);
1893 /* if we are in a join */
1894 if (ea_endpoint->ep_join_id)
1896 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1897 memcpy(&message->param, param, sizeof(union parameter));
1898 message_put(message);
1902 /* port MESSAGE_PROCEEDING */
1903 void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_type, union parameter *param)
1905 struct message *message;
1907 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1909 /* signal to call tool */
1910 admin_call_response(e_adminid, ADMIN_CALL_PROCEEDING, "", 0, 0, 0);
1912 e_state = EPOINT_STATE_OUT_PROCEEDING;
1913 /* check if pattern is availatle */
1914 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
1916 /* indicate patterns */
1917 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1918 message_put(message);
1920 /* connect audio, if not already */
1921 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1922 message->param.audiopath = CHANNEL_STATE_CONNECT;
1923 message_put(message);
1926 /* indicate no patterns */
1927 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1928 message_put(message);
1930 /* disconnect audio, if not already */
1931 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1932 message->param.audiopath = CHANNEL_STATE_HOLD;
1933 message_put(message);
1935 /* if we are in a call */
1936 if (ea_endpoint->ep_join_id)
1938 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1939 memcpy(&message->param, param, sizeof(union parameter));
1940 message_put(message);
1944 /* port MESSAGE_ALERTING */
1945 void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type, union parameter *param)
1947 struct message *message;
1949 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1951 /* signal to call tool */
1952 admin_call_response(e_adminid, ADMIN_CALL_ALERTING, "", 0, 0, 0);
1954 new_state(EPOINT_STATE_OUT_ALERTING);
1955 /* check if pattern is available */
1956 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
1958 /* indicate patterns */
1959 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1960 message_put(message);
1962 /* connect audio, if not already */
1963 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1964 message->param.audiopath = CHANNEL_STATE_CONNECT;
1965 message_put(message);
1968 /* indicate no patterns */
1969 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1970 message_put(message);
1972 /* disconnect audio, if not already */
1973 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1974 message->param.audiopath = CHANNEL_STATE_HOLD;
1975 message_put(message);
1977 /* if we are in a call */
1978 if (ea_endpoint->ep_join_id)
1980 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1981 memcpy(&message->param, param, sizeof(union parameter));
1982 message_put(message);
1986 /* port MESSAGE_CONNECT */
1987 void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, union parameter *param)
1989 struct message *message;
1991 unsigned long port_id = portlist->port_id;
1992 struct port_list *tportlist;
1994 struct interface *interface;
1996 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1998 /* signal to call tool */
1999 admin_call_response(e_adminid, ADMIN_CALL_CONNECT, numberrize_callerinfo(param->connectinfo.id,param->connectinfo.ntype), 0, 0, 0);
2001 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_connectinfo));
2002 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (start)\n", ea_endpoint->ep_serial);
2003 while(ea_endpoint->ep_portlist->next) /* as long as we have at least two ports */
2005 tportlist = ea_endpoint->ep_portlist;
2006 if (tportlist->port_id == port_id) /* if the first portlist is the calling one, the second must be a different one */
2007 tportlist = tportlist->next;
2008 if (tportlist->port_id == port_id)
2009 FATAL("EPOINT(%d) this should not happen since the portlist list must not have two links to the same port - exitting.\n");
2010 message = message_create(ea_endpoint->ep_serial, tportlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2011 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
2012 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2013 message_put(message);
2014 logmessage(message->type, &message->param, tportlist->port_id, DIRECTION_OUT);
2015 ea_endpoint->free_portlist(tportlist);
2017 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (end)\n", ea_endpoint->ep_serial);
2021 /* screen incoming connected id */
2022 interface = interface_first;
2025 if (!strcmp(e_connectinfo.interface, interface->name))
2029 interface = interface->next;
2032 do_screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface);
2034 /* screen connected name */
2036 SCPY(e_connectinfo.name, e_ext.name);
2038 /* add internal id to colp */
2039 SCPY(e_connectinfo.extension, e_ext.number);
2041 /* we store the connected port number */
2042 SCPY(e_extension_interface, e_connectinfo.interface);
2044 /* for internal and am calls, we get the extension's id */
2045 if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE)
2047 SCPY(e_connectinfo.id, e_ext.callerid);
2048 SCPY(e_connectinfo.extension, e_ext.number);
2049 e_connectinfo.itype = INFO_ITYPE_ISDN_EXTENSION;
2050 e_connectinfo.ntype = e_ext.callerid_type;
2051 e_connectinfo.present = e_ext.callerid_present;
2053 if (portlist->port_type==PORT_TYPE_VBOX_OUT)
2055 e_connectinfo.itype = INFO_ITYPE_VBOX;
2056 e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2059 new_state(EPOINT_STATE_CONNECT);
2061 /* set volume of rx and tx */
2062 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
2064 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2065 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2066 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
2067 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
2068 message_put(message);
2071 e_cfnr_call = e_cfnr_release = 0;
2072 if (e_ext.number[0])
2073 e_dtmf = 1; /* allow dtmf */
2076 /* other calls with no caller id (or not available for the extension) and force colp */
2077 if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE)
2079 e_connectinfo.present = INFO_PRESENT_NOTAVAIL;
2080 if (portlist->port_type==PORT_TYPE_DSS1_TE_OUT || portlist->port_type==PORT_TYPE_DSS1_NT_OUT) /* external extension answered */
2082 port = find_port_id(portlist->port_id);
2085 SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.id, &e_connectinfo.ntype));
2086 e_connectinfo.present = INFO_PRESENT_ALLOWED;
2091 /* send connect to join */
2092 if (ea_endpoint->ep_join_id)
2094 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2095 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
2096 message_put(message);
2098 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2099 message->param.audiopath = CHANNEL_STATE_CONNECT;
2100 message_put(message);
2101 } else if (!e_adminid)
2104 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have a callback, so we create a call with cbcaller: \"%s\".\n", ea_endpoint->ep_serial, e_cbcaller);
2105 SCPY(e_ext.number, e_cbcaller);
2106 new_state(EPOINT_STATE_IN_OVERLAP);
2107 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) callback from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2109 /* get extension's info about terminal */
2110 if (!read_extension(&e_ext, e_ext.number))
2112 /* extension doesn't exist */
2113 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2114 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
2115 new_state(EPOINT_STATE_OUT_DISCONNECT);
2116 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
2120 /* put prefix in front of e_cbdialing */
2121 SPRINT(buffer, "%s%s", e_ext.prefix, e_cbdialing);
2122 SCPY(e_dialinginfo.id, buffer);
2123 e_dialinginfo.itype = INFO_ITYPE_ISDN;
2124 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
2126 /* use caller id (or if exist: id_next_call) for this call */
2127 e_callerinfo.screen = INFO_SCREEN_NETWORK;
2128 SCPY(e_callerinfo.extension, e_ext.number);
2129 if (e_ext.id_next_call_present >= 0)
2131 SCPY(e_callerinfo.id, e_ext.id_next_call);
2132 e_callerinfo.present = e_ext.id_next_call_present;
2133 e_callerinfo.ntype = e_ext.id_next_call_type;
2134 e_ext.id_next_call_present = -1;
2135 /* extension is written */
2136 write_extension(&e_ext, e_ext.number);
2139 SCPY(e_callerinfo.id, e_ext.callerid);
2140 e_callerinfo.present = e_ext.callerid_present;
2141 e_callerinfo.ntype = e_ext.callerid_type;
2144 e_connectedmode = 1; /* dtmf-hangup & disconnect prevention */
2147 /* check if caller id is NOT authenticated */
2148 if (!parse_callbackauth(e_ext.number, &e_callbackinfo))
2150 /* make call state to enter password */
2151 new_state(EPOINT_STATE_IN_OVERLAP);
2152 e_action = &action_password_write;
2153 e_match_timeout = 0;
2154 e_match_to_action = NULL;
2155 e_dialinginfo.id[0] = '\0';
2156 e_extdialing = strchr(e_dialinginfo.id, '\0');
2157 e_password_timeout = now+20;
2161 /* incoming call (callback) */
2162 e_ruleset = ruleset_main;
2164 e_rule = e_ruleset->rule_first;
2166 e_extdialing = e_dialinginfo.id;
2167 if (e_dialinginfo.id[0])
2169 set_tone(portlist, "dialing");
2173 set_tone(portlist, "dialpbx");
2176 } else /* testcall */
2178 set_tone(portlist, "hold");
2181 /* start recording if enabled, not when answering machine answers */
2182 if (param->connectinfo.itype!=INFO_ITYPE_VBOX && e_ext.number[0] && e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO))
2184 /* check if we are a terminal */
2185 if (e_ext.number[0] == '\0')
2186 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
2189 port = find_port_id(portlist->port_id);
2191 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
2196 /* port MESSAGE_DISCONNECT MESSAGE_RELEASE */
2197 void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
2199 struct message *message;
2201 unsigned long port_id = portlist->port_id;
2205 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2207 /* signal to call tool */
2208 admin_call_response(e_adminid, (message_type==MESSAGE_DISCONNECT)?ADMIN_CALL_DISCONNECT:ADMIN_CALL_RELEASE, "", param->disconnectinfo.cause, param->disconnectinfo.location, 0);
2210 //#warning does this work? only disconnect when incoming port hat not already disconnected yet?
2211 if (e_state==EPOINT_STATE_IN_DISCONNECT && message_type!=MESSAGE_RELEASE)// || e_state==EPOINT_STATE_OUT_DISCONNECT || e_state==EPOINT_STATE_IDLE)
2213 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are already disconnected.\n", ea_endpoint->ep_serial);
2218 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current multipoint cause %d location %d, received cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location);
2219 collect_cause(&e_multipoint_cause, &e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location);
2220 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new multipoint cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location);
2222 /* check if we have more than one portlist relation and we just ignore the disconnect */
2223 if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist->next)
2225 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the disconnect was from a multipoint call. we just release that relation.\n", ea_endpoint->ep_serial);
2226 portlist = ea_endpoint->ep_portlist;
2229 if (portlist->port_id == port_id)
2231 portlist = portlist->next;
2234 FATAL("EPOINT(%d) no portlist related to the calling port.\n", ea_endpoint->ep_serial);
2235 if (message_type != MESSAGE_RELEASE)
2237 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2238 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2239 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2240 message_put(message);
2241 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2243 ea_endpoint->free_portlist(portlist);
2244 return; /* one relation removed */
2246 if (e_state == EPOINT_STATE_CONNECT)
2248 /* use cause from port after connect */
2249 cause = param->disconnectinfo.cause;
2250 location = param->disconnectinfo.location;
2253 /* use multipoint cause if no connect yet */
2254 if (e_multipoint_cause)
2256 cause = e_multipoint_cause;
2257 location = e_multipoint_location;
2260 cause = CAUSE_NOUSER;
2261 location = LOCATION_PRIVATE_LOCAL;
2265 e_cfnr_call = e_cfnr_release = 0;
2267 /* process hangup */
2268 process_hangup(e_join_cause, e_join_location);
2269 e_multipoint_cause = 0;
2270 e_multipoint_location = 0;
2272 if (message_type == MESSAGE_DISCONNECT)
2274 /* tone to disconnected end */
2275 SPRINT(buffer, "cause_%02x", cause);
2276 if (ea_endpoint->ep_portlist)
2277 set_tone(ea_endpoint->ep_portlist, buffer);
2279 new_state(EPOINT_STATE_IN_DISCONNECT);
2282 if (ea_endpoint->ep_join_id)
2284 int haspatterns = 0;
2285 /* check if pattern is available */
2286 if (ea_endpoint->ep_portlist)
2287 if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->early_b)
2288 if (joinpbx_countrelations(ea_endpoint->ep_join_id)==2 // we must count relations, in order not to disturb the conference ; NOTE: asterisk always counts two, since it is a point to point call
2289 && message_type != MESSAGE_RELEASE) // if we release, we are done
2293 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has patterns.\n", ea_endpoint->ep_serial);
2294 /* indicate patterns */
2295 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2296 message_put(message);
2297 /* connect audio, if not already */
2298 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2299 message->param.audiopath = CHANNEL_STATE_CONNECT;
2300 message_put(message);
2301 /* send disconnect */
2302 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2303 memcpy(&message->param, param, sizeof(union parameter));
2304 message_put(message);
2305 /* disable encryption if disconnected */
2306 //PERROR("REMOVE ME: state =%d, %d\n", e_crypt_state, e_crypt);
2308 cryptman_message(CI_DISCONNECT_IND, NULL, 0);
2312 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
2315 if (message_type == MESSAGE_RELEASE)
2316 ea_endpoint->free_portlist(portlist);
2317 release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, callcause, portcause */
2318 return; /* must exit here */
2321 /* port MESSAGE_TIMEOUT */
2322 void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type, union parameter *param)
2326 trace_header("TIMEOUT", DIRECTION_IN);
2327 message_type = MESSAGE_DISCONNECT;
2328 switch (param->state)
2330 case PORT_STATE_OUT_SETUP:
2331 case PORT_STATE_OUT_OVERLAP:
2332 add_trace("state", NULL, "outgoing setup/dialing");
2334 /* no user responding */
2335 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2336 return; /* must exit here */
2338 case PORT_STATE_IN_SETUP:
2339 case PORT_STATE_IN_OVERLAP:
2340 add_trace("state", NULL, "incoming setup/dialing");
2341 param->disconnectinfo.cause = CAUSE_INVALID; /* number incomplete */
2342 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2345 case PORT_STATE_OUT_PROCEEDING:
2346 add_trace("state", NULL, "outgoing proceeding");
2348 param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
2349 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2350 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2351 return; /* must exit here */
2353 case PORT_STATE_IN_PROCEEDING:
2354 add_trace("state", NULL, "incoming proceeding");
2355 param->disconnectinfo.cause = CAUSE_NOUSER;
2356 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL; /* no user responding */
2359 case PORT_STATE_OUT_ALERTING:
2360 add_trace("state", NULL, "outgoing alerting");
2362 param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
2363 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2364 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2365 return; /* must exit here */
2367 case PORT_STATE_CONNECT:
2368 add_trace("state", NULL, "connect");
2370 param->disconnectinfo.cause = CAUSE_NORMAL; /* normal */
2371 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2372 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2373 return; /* must exit here */
2375 case PORT_STATE_IN_ALERTING:
2376 add_trace("state", NULL, "incoming alerting");
2377 param->disconnectinfo.cause = CAUSE_NOANSWER;
2378 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2381 case PORT_STATE_IN_DISCONNECT:
2382 case PORT_STATE_OUT_DISCONNECT:
2383 add_trace("state", NULL, "disconnect");
2385 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
2386 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2387 return; /* must exit here */
2390 param->disconnectinfo.cause = 31; /* normal unspecified */
2391 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2394 /* release call, disconnect isdn */
2396 new_state(EPOINT_STATE_OUT_DISCONNECT);
2397 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2398 SCPY(e_tone, cause);
2401 set_tone(portlist, cause);
2402 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2403 portlist = portlist->next;
2405 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
2408 /* port MESSAGE_NOTIFY */
2409 void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, union parameter *param)
2411 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2413 struct message *message;
2417 /* signal to call tool */
2418 admin_call_response(e_adminid, ADMIN_CALL_NOTIFY, numberrize_callerinfo(param->notifyinfo.id,param->notifyinfo.ntype), 0, 0, param->notifyinfo.notify);
2419 if (param->notifyinfo.notify)
2421 e_rx_state = track_notify(e_rx_state, param->notifyinfo.notify);
2424 /* if we get notification from stack, local shows if we disabled/enabled audio stream */
2425 if (param->notifyinfo.local) switch(param->notifyinfo.notify)
2427 case INFO_NOTIFY_REMOTE_HOLD:
2428 case INFO_NOTIFY_USER_SUSPENDED:
2429 /* tell call about it */
2430 if (ea_endpoint->ep_join_id)
2432 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2433 message->param.audiopath = CHANNEL_STATE_HOLD;
2434 message_put(message);
2438 case INFO_NOTIFY_REMOTE_RETRIEVAL:
2439 case INFO_NOTIFY_USER_RESUMED:
2440 /* set volume of rx and tx */
2441 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
2442 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
2445 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2446 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2447 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
2448 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
2449 message_put(message);
2451 /* set current tone */
2453 set_tone(portlist, e_tone);
2454 /* tell call about it */
2455 if (ea_endpoint->ep_join_id)
2457 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2458 message->param.audiopath = CHANNEL_STATE_CONNECT;
2459 message_put(message);
2464 /* get name of notify */
2465 switch(param->notifyinfo.notify)
2471 logtext = "USER_SUSPENDED";
2474 logtext = "BEARER_SERVICE_CHANGED";
2477 logtext = "USER_RESUMED";
2480 logtext = "CONFERENCE_ESTABLISHED";
2483 logtext = "CONFERENCE_DISCONNECTED";
2486 logtext = "OTHER_PARTY_ADDED";
2489 logtext = "ISOLATED";
2492 logtext = "REATTACHED";
2495 logtext = "OTHER_PARTY_ISOLATED";
2498 logtext = "OTHER_PARTY_REATTACHED";
2501 logtext = "OTHER_PARTY_SPLIT";
2504 logtext = "OTHER_PARTY_DISCONNECTED";
2507 logtext = "CONFERENCE_FLOATING";
2510 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
2513 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
2516 logtext = "CALL_IS_A_WAITING_CALL";
2519 logtext = "DIVERSION_ACTIVATED";
2522 logtext = "RESERVED_CT_1";
2525 logtext = "RESERVED_CT_2";
2528 logtext = "REVERSE_CHARGING";
2531 logtext = "REMOTE_HOLD";
2534 logtext = "REMOTE_RETRIEVAL";
2537 logtext = "CALL_IS_DIVERTING";
2540 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
2545 /* notify call if available */
2546 if (ea_endpoint->ep_join_id)
2548 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOTIFY);
2549 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
2550 message_put(message);
2555 /* port MESSAGE_FACILITY */
2556 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
2558 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2560 struct message *message;
2562 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_FACILITY);
2563 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2564 message_put(message);
2567 /* port MESSAGE_SUSPEND */
2568 /* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
2569 void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
2571 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2573 /* epoint is now parked */
2574 ea_endpoint->ep_park = 1;
2575 memcpy(ea_endpoint->ep_park_callid, param->parkinfo.callid, sizeof(ea_endpoint->ep_park_callid));
2576 ea_endpoint->ep_park_len = (param->parkinfo.len>8)?8:param->parkinfo.len;
2578 /* remove port relation */
2579 ea_endpoint->free_portlist(portlist);
2582 /* port MESSAGE_RESUME */
2583 /* NOTE: before resume, the active-notification must be done in order to set call mixer */
2584 void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
2586 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2588 /* epoint is now resumed */
2589 ea_endpoint->ep_park = 0;
2594 /* port sends message to the endpoint
2596 void EndpointAppPBX::ea_message_port(unsigned long port_id, int message_type, union parameter *param)
2598 struct port_list *portlist;
2599 struct message *message;
2601 portlist = ea_endpoint->ep_portlist;
2604 if (port_id == portlist->port_id)
2606 portlist = portlist->next;
2610 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) warning: port is not related to this endpoint. This may happen, if port has been released after the message was created.\n", ea_endpoint->ep_serial);
2614 // PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
2615 switch(message_type)
2617 case MESSAGE_DATA: /* data from port */
2618 /* check if there is a call */
2619 if (!ea_endpoint->ep_join_id)
2621 /* continue if only one portlist */
2622 if (ea_endpoint->ep_portlist->next != NULL)
2624 /* forward message */
2625 message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2628 case MESSAGE_TONE_EOF: /* tone is end of file */
2629 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
2632 if (e_action->index == ACTION_VBOX_PLAY)
2636 if (e_action->index == ACTION_EFI)
2643 case MESSAGE_TONE_COUNTER: /* counter info received */
2644 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) received counter information: %d / %d seconds after start of tone.\n", ea_endpoint->ep_serial, param->counter.current, param->counter.max);
2646 if (e_action->index == ACTION_VBOX_PLAY)
2648 e_vbox_counter = param->counter.current;
2649 if (param->counter.max >= 0)
2650 e_vbox_counter_max = param->counter.max;
2654 /* PORT sends SETUP message */
2656 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call from callerid=%s, dialing=%s\n", ea_endpoint->ep_serial, param->setup.callerinfo.id, param->setup.dialinginfo.id);
2657 if (e_state!=EPOINT_STATE_IDLE)
2659 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
2662 port_setup(portlist, message_type, param);
2665 /* PORT sends INFORMATION message */
2666 case MESSAGE_INFORMATION: /* additional digits received */
2667 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call dialing more=%s (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, param->information.id, e_ext.number, e_callerinfo.id);
2668 port_information(portlist, message_type, param);
2671 /* PORT sends FACILITY message */
2672 case MESSAGE_FACILITY:
2673 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2674 port_facility(portlist, message_type, param);
2677 /* PORT sends DTMF message */
2678 case MESSAGE_DTMF: /* dtmf digits received */
2679 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf digit=%c (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, param->dtmf, e_ext.number, e_callerinfo.id);
2680 port_dtmf(portlist, message_type, param);
2683 /* PORT sends CRYPT message */
2684 case MESSAGE_CRYPT: /* crypt response received */
2685 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) crypt response=%d\n", ea_endpoint->ep_serial, param->crypt.type);
2686 port_crypt(portlist, message_type, param);
2689 /* PORT sends MORE message */
2690 case MESSAGE_OVERLAP:
2691 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) outgoing call is accepted [overlap dialing] (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2692 if (e_state != EPOINT_STATE_OUT_SETUP)
2694 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state (for port_list: another portlist might have changed the state already).\n", ea_endpoint->ep_serial);
2697 port_overlap(portlist, message_type, param);
2700 /* PORT sends PROCEEDING message */
2701 case MESSAGE_PROCEEDING: /* port is proceeding */
2702 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) outgoing call is proceeding (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2703 if (e_state!=EPOINT_STATE_OUT_SETUP
2704 && e_state!=EPOINT_STATE_OUT_OVERLAP)
2706 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in overlap state (for port_list: another portlist might have changed the state already).\n", ea_endpoint->ep_serial);
2709 port_proceeding(portlist, message_type, param);
2712 /* PORT sends ALERTING message */
2713 case MESSAGE_ALERTING:
2714 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) outgoing call is ringing (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2715 if (e_state!=EPOINT_STATE_OUT_SETUP
2716 && e_state!=EPOINT_STATE_OUT_OVERLAP
2717 && e_state!=EPOINT_STATE_OUT_PROCEEDING)
2719 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state (for port_list: another portlist might have changed the state already).\n", ea_endpoint->ep_serial);
2722 port_alerting(portlist, message_type, param);
2725 /* PORT sends CONNECT message */
2726 case MESSAGE_CONNECT:
2727 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) outgoing call connected to %s (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_connectinfo.id, e_ext.number, e_callerinfo.id);
2728 if (e_state!=EPOINT_STATE_OUT_SETUP
2729 && e_state!=EPOINT_STATE_OUT_OVERLAP
2730 && e_state!=EPOINT_STATE_OUT_PROCEEDING
2731 && e_state!=EPOINT_STATE_OUT_ALERTING)
2733 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
2736 port_connect(portlist, message_type, param);
2739 /* PORT sends DISCONNECT message */
2740 case MESSAGE_DISCONNECT: /* port is disconnected */
2741 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call disconnect with cause=%d location=%d (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, param->disconnectinfo.cause, param->disconnectinfo.location, e_ext.number, e_callerinfo.id);
2742 port_disconnect_release(portlist, message_type, param);
2745 /* PORT sends a RELEASE message */
2746 case MESSAGE_RELEASE: /* port releases */
2747 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) release with cause=%d location=%d (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, param->disconnectinfo.cause, param->disconnectinfo.location, e_ext.number, e_callerinfo.id);
2748 /* portlist is release at port_disconnect_release, thanx Paul */
2749 port_disconnect_release(portlist, message_type, param);
2752 /* PORT sends a TIMEOUT message */
2753 case MESSAGE_TIMEOUT:
2754 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received timeout (state=%d).\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->state);
2755 port_timeout(portlist, message_type, param);
2756 break; /* release */
2758 /* PORT sends a NOTIFY message */
2759 case MESSAGE_NOTIFY:
2760 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received notify.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2761 port_notify(portlist, message_type, param);
2764 /* PORT sends a SUSPEND message */
2765 case MESSAGE_SUSPEND:
2766 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received suspend.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2767 port_suspend(portlist, message_type, param);
2768 break; /* suspend */
2770 /* PORT sends a RESUME message */
2771 case MESSAGE_RESUME:
2772 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received resume.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2773 port_resume(portlist, message_type, param);
2777 /* port assigns bchannel */
2778 case MESSAGE_BCHANNEL: /* bchannel assignment messafe */
2779 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received bchannel message %d from port.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->bchannel.type);
2780 /* only one port is expected to be connected to bchannel */
2781 message = message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2782 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_IN);
2788 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received a wrong message: %d\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, message);
2791 /* Note: this endpoint may be destroyed, so we MUST return */
2795 /* messages from join
2797 /* join MESSAGE_CRYPT */
2798 void EndpointAppPBX::join_crypt(struct port_list *portlist, int message_type, union parameter *param)
2800 switch(param->crypt.type)
2802 /* message from remote port to "crypt manager" */
2803 case CU_ACTK_REQ: /* activate key-exchange */
2804 case CU_ACTS_REQ: /* activate shared key */
2805 case CU_DACT_REQ: /* deactivate */
2806 case CU_INFO_REQ: /* request last info message */
2807 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2810 /* message from "crypt manager" to user */
2811 case CU_ACTK_CONF: /* key-echange done */
2812 case CU_ACTS_CONF: /* shared key done */
2813 case CU_DACT_CONF: /* deactivated */
2814 case CU_DACT_IND: /* deactivated */
2815 case CU_ERROR_IND: /* receive error message */
2816 case CU_INFO_IND: /* receive info message */
2817 case CU_INFO_CONF: /* receive info message */
2818 encrypt_result(param->crypt.type, (char *)param->crypt.data);
2822 PERROR("EPOINT(%d) epoint with terminal '%s' (caller id '%s') unknown crypt message: '%d'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->crypt.type);
2826 /* join MESSAGE_INFORMATION */
2827 void EndpointAppPBX::join_information(struct port_list *portlist, int message_type, union parameter *param)
2829 struct message *message;
2835 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2836 memcpy(&message->param.information, ¶m->information, sizeof(struct dialing_info));
2837 message_put(message);
2838 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2839 portlist = portlist->next;
2843 /* join MESSAGE_FACILITY */
2844 void EndpointAppPBX::join_facility(struct port_list *portlist, int message_type, union parameter *param)
2846 struct message *message;
2848 if (!e_ext.facility)
2855 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_FACILITY);
2856 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2857 message_put(message);
2858 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2859 portlist = portlist->next;
2863 /* join MESSAGE_MORE */
2864 void EndpointAppPBX::join_overlap(struct port_list *portlist, int message_type, union parameter *param)
2866 struct message *message;
2868 new_state(EPOINT_STATE_IN_OVERLAP);
2871 if (e_join_pattern && e_ext.own_setup)
2873 /* disconnect audio */
2874 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2875 message->param.audiopath = CHANNEL_STATE_HOLD;
2876 message_put(message);
2878 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
2880 set_tone(portlist, "dialtone");
2883 if (e_ext.number[0])
2884 set_tone(portlist, "dialpbx");
2886 set_tone(portlist, "dialtone");
2889 /* join MESSAGE_PROCEEDING */
2890 void EndpointAppPBX::join_proceeding(struct port_list *portlist, int message_type, union parameter *param)
2892 struct message *message;
2894 new_state(EPOINT_STATE_IN_PROCEEDING);
2896 /* own proceeding tone */
2899 /* connect / disconnect audio */
2900 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2901 if (e_ext.own_proceeding)
2902 message->param.audiopath = CHANNEL_STATE_HOLD;
2904 message->param.audiopath = CHANNEL_STATE_CONNECT;
2905 message_put(message);
2907 // UCPY(e_join_tone, "proceeding");
2910 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
2911 message_put(message);
2912 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2914 set_tone(portlist, "proceeding");
2917 /* join MESSAGE_ALERTING */
2918 void EndpointAppPBX::join_alerting(struct port_list *portlist, int message_type, union parameter *param)
2920 struct message *message;
2922 new_state(EPOINT_STATE_IN_ALERTING);
2924 /* own alerting tone */
2927 /* connect / disconnect audio */
2928 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2929 if (e_ext.own_alerting)
2930 message->param.audiopath = CHANNEL_STATE_HOLD;
2932 message->param.audiopath = CHANNEL_STATE_CONNECT;
2933 message_put(message);
2937 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
2938 message_put(message);
2939 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2941 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
2943 set_tone(portlist, "ringing");
2946 if (e_ext.number[0])
2947 set_tone(portlist, "ringpbx");
2949 set_tone(portlist, "ringing");
2952 /* join MESSAGE_CONNECT */
2953 void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type, union parameter *param)
2955 struct message *message;
2957 new_state(EPOINT_STATE_CONNECT);
2958 // UCPY(e_join_tone, "");
2959 if (e_ext.number[0])
2960 e_dtmf = 1; /* allow dtmf */
2962 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_callerinfo));
2965 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
2966 memcpy(&message->param, param, sizeof(union parameter));
2968 /* screen clip if prefix is required */
2969 if (e_ext.number[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0])
2971 SCPY(message->param.connectinfo.id, e_ext.clip_prefix);
2972 SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype));
2973 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2976 /* use internal caller id */
2977 if (e_ext.number[0] && e_connectinfo.extension[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
2979 SCPY(message->param.connectinfo.id, e_connectinfo.extension);
2980 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2983 /* handle restricted caller ids */
2984 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);
2985 /* display callerid if desired for extension */
2986 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));
2988 /* use conp, if enabld */
2990 message->param.connectinfo.name[0] = '\0';
2993 message_put(message);
2994 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2996 set_tone(portlist, NULL);
2998 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2999 message->param.audiopath = CHANNEL_STATE_CONNECT;
3000 message_put(message);
3004 /* join MESSAGE_DISCONNECT MESSAGE_RELEASE */
3005 void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *param)
3008 struct message *message;
3009 struct port_list *portlist = NULL;
3012 /* be sure that we are active */
3014 e_tx_state = NOTIFY_STATE_ACTIVE;
3016 /* we are powerdialing, if e_powerdialing is set and limit is not exceeded if given */
3017 if (e_powerdialing && ((e_powercount+1)<e_powerlimit || e_powerlimit<1))
3019 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
3021 /* set time for power dialing */
3022 e_powerdialing = now_d + e_powerdelay; /* set redial in the future */
3025 /* set redial tone */
3026 if (ea_endpoint->ep_portlist)
3030 set_tone(ea_endpoint->ep_portlist, "redial");
3031 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);
3032 /* send proceeding when powerdialing and still setup (avoid dialing timeout) */
3033 if (e_state==EPOINT_STATE_IN_OVERLAP)
3035 new_state(EPOINT_STATE_IN_PROCEEDING);
3036 if (ea_endpoint->ep_portlist)
3038 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3039 message_put(message);
3040 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3042 /* caused the error, that the first knock sound was not there */
3043 /* set_tone(portlist, "proceeding"); */
3045 /* send display of powerdialing */
3046 if (e_ext.display_dialing)
3048 portlist = ea_endpoint->ep_portlist;
3051 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3053 SPRINT(message->param.notifyinfo.display, "Retry %d of %d", e_powercount, e_powerlimit);
3055 SPRINT(message->param.notifyinfo.display, "Retry %d", e_powercount);
3056 message_put(message);
3057 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3058 portlist = portlist->next;
3067 if ((e_state!=EPOINT_STATE_CONNECT
3068 && e_state!=EPOINT_STATE_OUT_DISCONNECT
3069 && e_state!=EPOINT_STATE_IN_OVERLAP
3070 && e_state!=EPOINT_STATE_IN_PROCEEDING
3071 && e_state!=EPOINT_STATE_IN_ALERTING)
3072 || !ea_endpoint->ep_portlist) /* or no port */
3074 process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
3075 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause); /* RELEASE_TYPE, join, port */
3076 return; /* must exit here */
3081 e_join_cause = param->disconnectinfo.cause;
3082 e_join_location = param->disconnectinfo.location;
3085 /* on release we need the audio again! */
3086 if (message_type == MESSAGE_RELEASE)
3089 ea_endpoint->ep_join_id = 0;
3091 /* disconnect and select tone */
3092 new_state(EPOINT_STATE_OUT_DISCONNECT);
3093 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
3094 /* if own_cause, we must release the join */
3095 if (e_ext.own_cause /* own cause */
3096 || !e_join_pattern) /* no patterns */
3098 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);
3099 if (message_type != MESSAGE_RELEASE)
3100 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
3102 } else /* else we enable audio */
3104 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3105 message->param.audiopath = CHANNEL_STATE_CONNECT;
3106 message_put(message);
3108 /* send disconnect message */
3109 SCPY(e_tone, cause);
3110 portlist = ea_endpoint->ep_portlist;
3113 set_tone(portlist, cause);
3114 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
3115 portlist = portlist->next;
3119 /* join MESSAGE_SETUP */
3120 void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, union parameter *param)
3122 struct message *message;
3123 struct interface *interface;
3125 /* if we already in setup state, we just update the dialing with new digits */
3126 if (e_state == EPOINT_STATE_OUT_SETUP
3127 || e_state == EPOINT_STATE_OUT_OVERLAP)
3129 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we are in setup state, so we do overlap dialing.\n", ea_endpoint->ep_serial);
3130 /* if digits changed, what we have already dialed */
3131 if (!!strncmp(e_dialinginfo.id,param->setup.dialinginfo.id,strlen(e_dialinginfo.id)))
3133 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);
3134 /* release all ports */
3135 while((portlist = ea_endpoint->ep_portlist))
3137 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
3138 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
3139 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3140 message_put(message);
3141 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3142 ea_endpoint->free_portlist(portlist);
3145 /* disconnect audio */
3146 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3147 message->param.audiopath = CHANNEL_STATE_HOLD;
3148 message_put(message);
3150 /* get dialing info */
3151 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3152 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3153 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3154 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3155 new_state(EPOINT_STATE_OUT_OVERLAP);
3158 e_redial = now_d + 1; /* set redial one second in the future */
3161 /* if we have a pending redial, so we just adjust the dialing number */
3164 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);
3165 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3168 if (!ea_endpoint->ep_portlist)
3170 PERROR("ERROR: overlap dialing to a NULL port relation\n");
3172 if (ea_endpoint->ep_portlist->next)
3174 PERROR("ERROR: overlap dialing to a port_list port relation\n");
3176 if (e_state == EPOINT_STATE_OUT_SETUP)
3179 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);
3180 SCAT(e_dialing_queue, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3184 /* get what we have not dialed yet */
3185 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));
3186 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
3187 SCPY(message->param.information.id, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3188 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
3189 message_put(message);
3190 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3192 /* always store what we have dialed or queued */
3193 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3197 if (e_state != EPOINT_STATE_IDLE)
3199 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
3202 /* if an internal extension is dialed, copy that number */
3203 if (param->setup.dialinginfo.itype==INFO_ITYPE_ISDN_EXTENSION || param->setup.dialinginfo.itype==INFO_ITYPE_VBOX)
3204 SCPY(e_ext.number, param->setup.dialinginfo.id);
3205 /* if an internal extension is dialed, get extension's info about caller */
3206 if (e_ext.number[0])
3208 if (!read_extension(&e_ext, e_ext.number))
3210 e_ext.number[0] = '\0';
3211 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the called terminal='%s' is not found in directory tree!\n", ea_endpoint->ep_serial, e_ext.number);
3215 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3216 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3217 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3218 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3220 /* process (voice over) data calls */
3221 if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO)
3223 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) handling data call as audio call: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
3224 memset(&e_capainfo, 0, sizeof(e_capainfo));
3225 e_capainfo.bearer_capa = INFO_BC_AUDIO;
3226 e_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
3227 e_capainfo.bearer_info1 = (options.law=='u')?INFO_INFO1_ULAW:INFO_INFO1_ALAW;
3230 new_state(EPOINT_STATE_OUT_SETUP);
3231 /* call special setup routine */
3235 /* join MESSAGE_mISDNSIGNAL */
3236 void EndpointAppPBX::join_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param)
3238 struct message *message;
3242 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
3243 memcpy(&message->param, param, sizeof(union parameter));
3244 message_put(message);
3245 portlist = portlist->next;
3249 /* join MESSAGE_NOTIFY */
3250 void EndpointAppPBX::join_notify(struct port_list *portlist, int message_type, union parameter *param)
3252 struct message *message;
3255 if (param->notifyinfo.notify)
3257 new_state = track_notify(e_tx_state, param->notifyinfo.notify);
3258 // /* if notification was generated locally, we turn hold music on/off */
3259 // if (param->notifyinfo.local)
3260 // 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)
3265 if (new_state!=NOTIFY_STATE_HOLD && new_state!=NOTIFY_STATE_SUSPEND)
3267 if (!strcmp(e_tone, "hold")) // don't interrupt other tones
3271 set_tone(portlist, "");
3272 portlist = portlist->next;
3275 portlist = ea_endpoint->ep_portlist;
3280 if (new_state==NOTIFY_STATE_HOLD || new_state==NOTIFY_STATE_SUSPEND)
3284 set_tone(portlist, "hold");
3285 portlist = portlist->next;
3287 portlist = ea_endpoint->ep_portlist;
3292 /* save new state */
3293 e_tx_state = new_state;
3296 /* notify port(s) about it */
3299 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3300 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
3301 /* handle restricted caller ids */
3302 apply_callerid_restriction(&e_ext, message->param.notifyinfo.id, &message->param.notifyinfo.ntype, &message->param.notifyinfo.present, 0, message->param.notifyinfo.extension, NULL);
3303 /* display callerid if desired for extension */
3304 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));
3305 message_put(message);
3306 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3307 portlist = portlist->next;
3311 /* JOIN sends messages to the endpoint
3313 void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, union parameter *param)
3315 struct port_list *portlist;
3316 struct message *message;
3320 PERROR("EPOINT(%d) error: JOIN == NULL.\n", ea_endpoint->ep_serial);
3324 portlist = ea_endpoint->ep_portlist;
3326 /* send MESSAGE_DATA to port */
3327 if (message_type == MESSAGE_DATA)
3329 if (join_id == ea_endpoint->ep_join_id) // still linked with JOIN
3331 /* skip if no port relation */
3334 /* skip if more than one port relation */
3337 /* forward audio data to port */
3338 message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3343 // 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);
3344 switch(message_type)
3346 /* JOIN SENDS TONE message */
3348 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);
3349 set_tone(portlist, param->tone.name);
3352 /* JOIN SENDS CRYPT message */
3354 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);
3355 join_crypt(portlist, message_type, param);
3358 /* JOIN sends INFORMATION message */
3359 case MESSAGE_INFORMATION:
3360 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);
3361 join_information(portlist, message_type, param);
3364 /* JOIN sends FACILITY message */
3365 case MESSAGE_FACILITY:
3366 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);
3367 join_facility(portlist, message_type, param);
3370 /* JOIN sends OVERLAP message */
3371 case MESSAGE_OVERLAP:
3372 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);
3373 if (e_state!=EPOINT_STATE_IN_SETUP
3374 && e_state!=EPOINT_STATE_IN_OVERLAP)
3376 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3379 join_overlap(portlist, message_type, param);
3382 /* JOIN sends PROCEEDING message */
3383 case MESSAGE_PROCEEDING:
3384 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);
3385 if(e_state!=EPOINT_STATE_IN_OVERLAP)
3387 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3390 join_proceeding(portlist, message_type, param);
3393 /* JOIN sends ALERTING message */
3394 case MESSAGE_ALERTING:
3395 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);
3396 if (e_state!=EPOINT_STATE_IN_OVERLAP
3397 && e_state!=EPOINT_STATE_IN_PROCEEDING)
3399 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state.\n", ea_endpoint->ep_serial);
3402 join_alerting(portlist, message_type, param);
3405 /* JOIN sends CONNECT message */
3406 case MESSAGE_CONNECT:
3407 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);
3408 if (e_state!=EPOINT_STATE_IN_OVERLAP
3409 && e_state!=EPOINT_STATE_IN_PROCEEDING
3410 && e_state!=EPOINT_STATE_IN_ALERTING)
3412 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
3415 join_connect(portlist, message_type, param);
3418 /* JOIN sends DISCONNECT/RELEASE message */
3419 case MESSAGE_DISCONNECT: /* JOIN disconnect */
3420 case MESSAGE_RELEASE: /* JOIN releases */
3421 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);
3422 join_disconnect_release(message_type, param);
3425 /* JOIN sends SETUP message */
3427 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);
3428 join_setup(portlist, message_type, param);
3431 /* JOIN sends special mISDNSIGNAL message */
3432 case MESSAGE_mISDNSIGNAL: /* isdn message to port */
3433 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);
3434 join_mISDNsignal(portlist, message_type, param);
3438 /* JOIN requests bchannel */
3439 case MESSAGE_BCHANNEL: /* indicates the need of own bchannel access */
3440 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);
3441 /* only one port is expected to be connected to bchannel */
3448 set_tone(portlist, NULL);
3449 message = message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3450 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3454 /* JOIN has pattern available */
3455 case MESSAGE_PATTERN: /* indicating pattern available */
3456 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);
3457 if (!e_join_pattern)
3459 PDEBUG(DEBUG_EPOINT, "-> pattern becomes available\n");
3464 set_tone(portlist, NULL);
3465 portlist = portlist->next;
3467 /* connect our audio tx and rx (blueboxing should be possibe before connect :)*/
3468 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3469 message->param.audiopath = CHANNEL_STATE_CONNECT;
3470 message_put(message);
3471 // /* tell remote epoint to connect audio also, because we like to hear the patterns */
3472 // message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_REMOTE_AUDIO);
3473 // message->param.audiopath = CHANNEL_STATE_CONNECT;
3474 // message_put(message);
3475 // patterns are available, remote already connected audio
3479 /* JOIN has no pattern available */
3480 case MESSAGE_NOPATTERN: /* indicating no pattern available */
3481 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);
3484 PDEBUG(DEBUG_EPOINT, "-> pattern becomes unavailable\n");
3486 /* disconnect our audio tx and rx */
3487 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3488 message->param.audiopath = CHANNEL_STATE_HOLD;
3489 message_put(message);
3494 /* JOIN (dunno at the moment) */
3495 case MESSAGE_REMOTE_AUDIO:
3496 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);
3497 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3498 message->param.audiopath = param->channel;
3499 message_put(message);
3503 /* JOIN sends a notify message */
3504 case MESSAGE_NOTIFY:
3505 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);
3506 join_notify(portlist, message_type, param);
3510 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);
3515 /* pick_join will connect the first incoming call found. the endpoint
3516 * will receivce a MESSAGE_CONNECT.
3518 int match_list(char *list, char *item)
3520 char *end, *next = NULL;
3522 /* no list make matching */
3528 /* eliminate white spaces */
3529 while (*list <= ' ')
3536 /* if end of list is reached, we return */
3537 if (list[0] == '\0')
3539 /* if we have more than one entry (left) */
3540 if ((end = strchr(list, ',')))
3543 next = end = strchr(list, '\0');
3544 while (*(end-1) <= ' ')
3546 /* if string part matches item */
3547 if (!strncmp(list, item, end-list))
3553 void EndpointAppPBX::pick_join(char *extensions)
3555 struct message *message;
3556 struct port_list *portlist;
3558 class EndpointAppPBX *eapp, *found;
3560 class JoinPBX *joinpbx;
3561 struct join_relation *relation;
3564 /* find an endpoint that is ringing internally or vbox with higher priority */
3567 eapp = apppbx_first;
3570 if (eapp!=this && ea_endpoint->ep_portlist)
3572 portlist = eapp->ea_endpoint->ep_portlist;
3575 if ((port = find_port_id(portlist->port_id)))
3577 if (port->p_type == PORT_TYPE_VBOX_OUT)
3579 if (match_list(extensions, eapp->e_ext.number))
3586 if ((port->p_type==PORT_TYPE_DSS1_NT_OUT || port->p_type==PORT_TYPE_DSS1_TE_OUT)
3587 && port->p_state==PORT_STATE_OUT_ALERTING)
3588 if (match_list(extensions, eapp->e_ext.number))
3593 portlist = portlist->next;
3601 /* if no endpoint found */
3604 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);
3606 set_tone(ea_endpoint->ep_portlist, "cause_10");
3607 message_disconnect_port(ea_endpoint->ep_portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
3608 new_state(EPOINT_STATE_OUT_DISCONNECT);
3613 if (ea_endpoint->ep_join_id)
3615 PERROR("EPOINT(%d) we already have a join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3618 if (!eapp->ea_endpoint->ep_join_id)
3620 PERROR("EPOINT(%d) ringing endpoint has no join.\n", ea_endpoint->ep_serial);
3623 join = find_join_id(eapp->ea_endpoint->ep_join_id);
3626 PERROR("EPOINT(%d) ringing endpoint's join not found.\n", ea_endpoint->ep_serial);
3629 if (join->j_type != JOIN_TYPE_PBX)
3631 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ringing endpoint's join is not a PBX join, so we must reject.\n", ea_endpoint->ep_serial);
3634 joinpbx = (class JoinPBX *)join;
3635 relation = joinpbx->j_relation;
3638 PERROR("EPOINT(%d) ringing endpoint's join has no relation. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3641 while (relation->epoint_id != eapp->ea_endpoint->ep_serial)
3643 relation = relation->next;
3646 PERROR("EPOINT(%d) ringing endpoint's join has no relation to that join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3651 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found ringing endpoint: %d.\n", ea_endpoint->ep_serial, eapp->ea_endpoint->ep_serial);
3653 if (options.deb & DEBUG_EPOINT)
3655 class Join *debug_c = join_first;
3656 class Endpoint *debug_e = epoint_first;
3657 class Port *debug_p = port_first;
3659 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(before)");
3661 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3664 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3665 debug_c = debug_c->next;
3667 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3670 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3671 debug_e = debug_e->next;
3673 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3676 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld (active)\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3677 debug_p = debug_p->next;
3682 ea_endpoint->ep_join_id = eapp->ea_endpoint->ep_join_id; /* we get the join */
3683 relation->epoint_id = ea_endpoint->ep_serial; /* the join gets us */
3684 eapp->ea_endpoint->ep_join_id = 0; /* the ringing endpoint will get disconnected */
3686 /* connnecting our endpoint */
3687 new_state(EPOINT_STATE_CONNECT);
3689 set_tone(ea_endpoint->ep_portlist, NULL);
3691 /* now we send a release to the ringing endpoint */
3692 message = message_create(ea_endpoint->ep_join_id, eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3693 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
3694 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3695 message_put(message);
3697 /* we send a connect to the join with our caller id */
3698 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CONNECT);
3699 SCPY(message->param.connectinfo.id, e_callerinfo.id);
3700 message->param.connectinfo.present = e_callerinfo.present;
3701 message->param.connectinfo.screen = e_callerinfo.screen;
3702 message->param.connectinfo.itype = e_callerinfo.itype;
3703 message->param.connectinfo.ntype = e_callerinfo.ntype;
3704 message_put(message);
3706 /* we send a connect to our port with the remote callerid */
3707 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3708 SCPY(message->param.connectinfo.id, eapp->e_callerinfo.id);
3709 message->param.connectinfo.present = eapp->e_callerinfo.present;
3710 message->param.connectinfo.screen = eapp->e_callerinfo.screen;
3711 message->param.connectinfo.itype = eapp->e_callerinfo.itype;
3712 message->param.connectinfo.ntype = eapp->e_callerinfo.ntype;
3713 /* handle restricted caller ids */
3714 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);
3715 /* display callerid if desired for extension */
3716 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));
3717 message_put(message);
3719 /* we send a connect to the audio path (not for vbox) */
3720 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3721 message->param.audiopath = CHANNEL_STATE_CONNECT;
3722 message_put(message);
3724 /* beeing paranoid, we make call update */
3725 joinpbx->j_updatebridge = 1;
3727 if (options.deb & DEBUG_EPOINT)
3729 class Join *debug_c = join_first;
3730 class Endpoint *debug_e = epoint_first;
3731 class Port *debug_p = port_first;
3733 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(after)");
3735 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3738 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3739 debug_c = debug_c->next;
3741 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3744 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3745 debug_e = debug_e->next;
3747 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3750 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3751 debug_p = debug_p->next;
3757 /* join calls (look for a join that is on hold (same isdn interface/terminal))
3759 void EndpointAppPBX::join_join(void)
3761 struct message *message;
3762 struct join_relation *our_relation, *other_relation;
3763 struct join_relation **our_relation_pointer, **other_relation_pointer;
3764 class Join *our_join, *other_join;
3765 class JoinPBX *our_joinpbx, *other_joinpbx;
3766 class EndpointAppPBX *other_eapp; class Endpoint *temp_epoint;
3767 class Port *our_port, *other_port;
3768 class Pdss1 *our_pdss1, *other_pdss1;
3770 /* are we a candidate to join a join */
3771 our_join = find_join_id(ea_endpoint->ep_join_id);
3774 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3777 if (our_join->j_type != JOIN_TYPE_PBX)
3779 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: join is not a pbx join.\n", ea_endpoint->ep_serial);
3782 our_joinpbx = (class JoinPBX *)our_join;
3783 if (!ea_endpoint->ep_portlist)
3785 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
3788 if (!e_ext.number[0])
3790 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
3793 our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
3796 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
3799 if ((our_port->p_type&PORT_CLASS_mISDN_MASK) != PORT_CLASS_mISDN_DSS1)
3801 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not isdn.\n", ea_endpoint->ep_serial);
3804 our_pdss1 = (class Pdss1 *)our_port;
3806 /* find an endpoint that is on hold and has the same mISDNport that we are on */
3807 other_eapp = apppbx_first;
3810 if (other_eapp == this)
3812 other_eapp = other_eapp->next;
3815 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);
3816 if (other_eapp->e_ext.number[0] /* has terminal */
3817 && other_eapp->ea_endpoint->ep_portlist /* has port */
3818 && other_eapp->ea_endpoint->ep_join_id) /* has join */
3820 other_port = find_port_id(other_eapp->ea_endpoint->ep_portlist->port_id);
3821 if (other_port) /* port still exists */
3823 if (other_port->p_type==PORT_TYPE_DSS1_NT_OUT
3824 || other_port->p_type==PORT_TYPE_DSS1_NT_IN) /* port is isdn nt-mode */
3826 other_pdss1 = (class Pdss1 *)other_port;
3827 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);
3828 if (other_pdss1->p_m_hold /* port is on hold */
3829 && other_pdss1->p_m_mISDNport == our_pdss1->p_m_mISDNport /* same isdn interface */
3830 && other_pdss1->p_m_d_ces == our_pdss1->p_m_d_ces) /* same tei+sapi */
3834 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of other type!\n", ea_endpoint->ep_serial);
3838 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port doesn't exist enymore.\n", ea_endpoint->ep_serial);
3841 other_eapp = other_eapp->next;
3845 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn interface with port on hold.\n", ea_endpoint->ep_serial);
3848 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port on hold found.\n", ea_endpoint->ep_serial);
3850 /* if we have the same join */
3851 if (other_eapp->ea_endpoint->ep_join_id == ea_endpoint->ep_join_id)
3853 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we an the other have the same join.\n", ea_endpoint->ep_serial);
3856 other_join = find_join_id(other_eapp->ea_endpoint->ep_join_id);
3859 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3862 if (other_join->j_type != JOIN_TYPE_PBX)
3864 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join is not a pbx join.\n", ea_endpoint->ep_serial);
3867 other_joinpbx = (class JoinPBX *)other_join;
3868 if (our_joinpbx->j_partyline && other_joinpbx->j_partyline)
3870 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both joins are partylines.\n", ea_endpoint->ep_serial);
3874 /* remove relation to endpoint for join on hold */
3875 other_relation = other_joinpbx->j_relation;
3876 other_relation_pointer = &other_joinpbx->j_relation;
3877 while(other_relation)
3879 if (other_relation->epoint_id == other_eapp->ea_endpoint->ep_serial)
3881 /* detach other endpoint on hold */
3882 *other_relation_pointer = other_relation->next;
3883 FREE(other_relation, sizeof(struct join_relation));
3885 other_relation = *other_relation_pointer;
3886 other_eapp->ea_endpoint->ep_join_id = NULL;
3890 /* change join/hold pointer of endpoint to the new join */
3891 temp_epoint = find_epoint_id(other_relation->epoint_id);
3894 if (temp_epoint->ep_join_id == other_join->j_serial)
3895 temp_epoint->ep_join_id = our_join->j_serial;
3898 other_relation_pointer = &other_relation->next;
3899 other_relation = other_relation->next;
3901 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint on hold removed, other enpoints on join relinked (to our join).\n", ea_endpoint->ep_serial);
3903 /* join call relations */
3904 our_relation = our_joinpbx->j_relation;
3905 our_relation_pointer = &our_joinpbx->j_relation;
3908 our_relation_pointer = &our_relation->next;
3909 our_relation = our_relation->next;
3911 *our_relation_pointer = other_joinpbx->j_relation;
3912 other_joinpbx->j_relation = NULL;
3913 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) relations joined.\n", ea_endpoint->ep_serial);
3915 /* release endpoint on hold */
3916 message = message_create(other_joinpbx->j_serial, other_eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3917 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */
3918 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3919 message_put(message);
3921 /* if we are not a partyline, we get partyline state from other join */
3922 our_joinpbx->j_partyline += other_joinpbx->j_partyline;
3924 /* remove empty join */
3926 PDEBUG(DEBUG_EPOINT, "EPOINT(%d)d-join completely removed!\n");
3928 /* mixer must update */
3929 our_joinpbx->j_updatebridge = 1; /* update mixer flag */
3931 /* we send a retrieve to that endpoint */
3932 // mixer will update the hold-state of the join and send it to the endpoints is changes
3936 /* check if we have an external call
3937 * this is used to check for encryption ability
3939 int EndpointAppPBX::check_external(char **errstr, class Port **port)
3941 struct join_relation *relation;
3943 class JoinPBX *joinpbx;
3944 class Endpoint *epoint;
3946 /* some paranoia check */
3947 if (!ea_endpoint->ep_portlist)
3949 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we have no port.\n", ea_endpoint->ep_serial);
3950 *errstr = "No Call";
3953 if (!e_ext.number[0])
3955 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we are not internal extension.\n", ea_endpoint->ep_serial);
3956 *errstr = "No Call";
3960 /* check if we have a join with 2 parties */
3961 join = find_join_id(ea_endpoint->ep_join_id);
3964 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have currently no join.\n", ea_endpoint->ep_serial);
3965 *errstr = "No Call";
3968 if (join->j_type != JOIN_TYPE_PBX)
3970 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join is not a pbx join.\n", ea_endpoint->ep_serial);
3971 *errstr = "No PBX Call";
3974 joinpbx = (class JoinPBX *)join;
3975 relation = joinpbx->j_relation;
3978 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no relation.\n", ea_endpoint->ep_serial);
3979 *errstr = "No Call";
3982 if (!relation->next)
3984 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd relation.\n", ea_endpoint->ep_serial);
3985 *errstr = "No Call";
3988 if (relation->next->next)
3990 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has more than two relations.\n", ea_endpoint->ep_serial);
3991 *errstr = "Err: Conference";
3994 if (relation->epoint_id == ea_endpoint->ep_serial)
3996 relation = relation->next;
3997 if (relation->epoint_id == ea_endpoint->ep_serial)
3999 PERROR("EPOINT(%d) SOFTWARE ERROR: both join relations are related to our endpoint.\n", ea_endpoint->ep_serial);
4000 *errstr = "Software Error";
4005 /* check remote port for external call */
4006 epoint = find_epoint_id(relation->epoint_id);
4009 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd endpoint.\n", ea_endpoint->ep_serial);
4010 *errstr = "No Call";
4013 if (!epoint->ep_portlist)
4015 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not port.\n", ea_endpoint->ep_serial);
4016 *errstr = "No Call";
4019 *port = find_port_id(epoint->ep_portlist->port_id);
4022 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has an none existing port.\n", ea_endpoint->ep_serial);
4023 *errstr = "No Call";
4026 if (((*port)->p_type&PORT_CLASS_mISDN_MASK)!=PORT_CLASS_mISDN_DSS1) /* port is not external isdn */
4028 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not an external port.\n", ea_endpoint->ep_serial);
4029 *errstr = "No Ext Call";
4032 if ((*port)->p_state != PORT_STATE_CONNECT)
4034 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint's port is not in connected state.\n", ea_endpoint->ep_serial);
4035 *errstr = "No Ext Connect";
4041 void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsigned long port_id, int dir)
4043 char *logtext = "unknown";
4046 switch(message_type)
4049 trace_header("SETUP", dir);
4050 if (dir == DIRECTION_OUT)
4051 add_trace("to", NULL, "CH(%lu)", port_id);
4052 if (dir == DIRECTION_IN)
4053 add_trace("from", NULL, "CH(%lu)", port_id);
4054 if (param->setup.callerinfo.extension[0])
4055 add_trace("extension", NULL, "%s", param->setup.callerinfo.extension);
4056 add_trace("caller id", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype));
4057 switch(param->setup.callerinfo.present)
4059 case INFO_PRESENT_RESTRICTED:
4060 add_trace("caller id", "present", "restricted");
4062 case INFO_PRESENT_ALLOWED:
4063 add_trace("caller id", "present", "allowed");
4066 add_trace("caller id", "present", "not available");
4068 if (param->setup.redirinfo.id[0])
4070 add_trace("redir'ing", "number", "%s", numberrize_callerinfo(param->setup.redirinfo.id, param->setup.redirinfo.ntype));
4071 switch(param->setup.redirinfo.present)
4073 case INFO_PRESENT_RESTRICTED:
4074 add_trace("redir'ing", "present", "restricted");
4076 case INFO_PRESENT_ALLOWED:
4077 add_trace("redir'ing", "present", "allowed");
4080 add_trace("redir'ing", "present", "not available");
4083 if (param->setup.dialinginfo.id[0])
4084 add_trace("dialing", NULL, "%s", param->setup.dialinginfo.id);
4088 case MESSAGE_OVERLAP:
4089 trace_header("SETUP ACKNOWLEDGE", dir);
4090 if (dir == DIRECTION_OUT)
4091 add_trace("to", NULL, "CH(%lu)", port_id);
4092 if (dir == DIRECTION_IN)
4093 add_trace("from", NULL, "CH(%lu)", port_id);
4097 case MESSAGE_PROCEEDING:
4098 trace_header("PROCEEDING", dir);
4099 if (dir == DIRECTION_OUT)
4100 add_trace("to", NULL, "CH(%lu)", port_id);
4101 if (dir == DIRECTION_IN)
4102 add_trace("from", NULL, "CH(%lu)", port_id);
4106 case MESSAGE_ALERTING:
4107 trace_header("ALERTING", dir);
4108 if (dir == DIRECTION_OUT)
4109 add_trace("to", NULL, "CH(%lu)", port_id);
4110 if (dir == DIRECTION_IN)
4111 add_trace("from", NULL, "CH(%lu)", port_id);
4115 case MESSAGE_CONNECT:
4116 trace_header("CONNECT", dir);
4117 if (dir == DIRECTION_OUT)
4118 add_trace("to", NULL, "CH(%lu)", port_id);
4119 if (dir == DIRECTION_IN)
4120 add_trace("from", NULL, "CH(%lu)", port_id);
4121 if (param->connectinfo.extension[0])
4122 add_trace("extension", NULL, "%s", param->connectinfo.extension);
4123 add_trace("connect id", "number", "%s", numberrize_callerinfo(param->connectinfo.id, param->connectinfo.ntype));
4124 switch(param->connectinfo.present)
4126 case INFO_PRESENT_RESTRICTED:
4127 add_trace("connect id", "present", "restricted");
4129 case INFO_PRESENT_ALLOWED:
4130 add_trace("connect id", "present", "allowed");
4133 add_trace("connect id", "present", "not available");
4138 case MESSAGE_DISCONNECT:
4139 case MESSAGE_RELEASE:
4140 if (message_type == MESSAGE_DISCONNECT)
4141 trace_header("DISCONNECT", dir);
4143 trace_header("RELEASE", dir);
4144 if (dir == DIRECTION_OUT)
4145 add_trace("to", NULL, "CH(%lu)", port_id);
4146 if (dir == DIRECTION_IN)
4147 add_trace("from", NULL, "CH(%lu)", port_id);
4148 add_trace("cause", "value", "%d", param->disconnectinfo.cause);
4149 switch(param->disconnectinfo.location)
4152 add_trace("cause", "location", "0-User");
4154 case LOCATION_PRIVATE_LOCAL:
4155 add_trace("cause", "location", "1-Local-PBX");
4157 case LOCATION_PUBLIC_LOCAL:
4158 add_trace("cause", "location", "2-Local-Exchange");
4160 case LOCATION_TRANSIT:
4161 add_trace("cause", "location", "3-Transit");
4163 case LOCATION_PUBLIC_REMOTE:
4164 add_trace("cause", "location", "4-Remote-Exchange");
4166 case LOCATION_PRIVATE_REMOTE:
4167 add_trace("cause", "location", "5-Remote-PBX");
4169 case LOCATION_INTERNATIONAL:
4170 add_trace("cause", "location", "7-International-Exchange");
4172 case LOCATION_BEYOND:
4173 add_trace("cause", "location", "10-Beyond-Interworking");
4176 add_trace("cause", "location", "%d", param->disconnectinfo.location);
4181 case MESSAGE_NOTIFY:
4182 switch(param->notifyinfo.notify)
4188 logtext = "USER_SUSPENDED";
4191 logtext = "BEARER_SERVICE_CHANGED";
4194 logtext = "USER_RESUMED";
4197 logtext = "CONFERENCE_ESTABLISHED";
4200 logtext = "CONFERENCE_DISCONNECTED";
4203 logtext = "OTHER_PARTY_ADDED";
4206 logtext = "ISOLATED";
4209 logtext = "REATTACHED";
4212 logtext = "OTHER_PARTY_ISOLATED";
4215 logtext = "OTHER_PARTY_REATTACHED";
4218 logtext = "OTHER_PARTY_SPLIT";
4221 logtext = "OTHER_PARTY_DISCONNECTED";
4224 logtext = "CONFERENCE_FLOATING";
4227 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
4230 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
4233 logtext = "CALL_IS_A_WAITING_CALL";
4236 logtext = "DIVERSION_ACTIVATED";
4239 logtext = "RESERVED_CT_1";
4242 logtext = "RESERVED_CT_2";
4245 logtext = "REVERSE_CHARGING";
4248 logtext = "REMOTE_HOLD";
4251 logtext = "REMOTE_RETRIEVAL";
4254 logtext = "CALL_IS_DIVERTING";
4257 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
4261 trace_header("NOTIFY", dir);
4262 if (dir == DIRECTION_OUT)
4263 add_trace("to", NULL, "CH(%lu)", port_id);
4264 if (dir == DIRECTION_IN)
4265 add_trace("from", NULL, "CH(%lu)", port_id);
4266 if (param->notifyinfo.notify)
4267 add_trace("indicator", NULL, "%s", logtext);
4268 if (param->notifyinfo.id[0])
4270 add_trace("redir'on", "number", "%s", numberrize_callerinfo(param->notifyinfo.id, param->notifyinfo.ntype));
4271 switch(param->notifyinfo.present)
4273 case INFO_PRESENT_RESTRICTED:
4274 add_trace("redir'on", "present", "restricted");
4276 case INFO_PRESENT_ALLOWED:
4277 add_trace("redir'on", "present", "allowed");
4280 add_trace("redir'on", "present", "not available");
4283 if (param->notifyinfo.display[0])
4284 add_trace("display", NULL, "%s", param->notifyinfo.display);
4288 case MESSAGE_INFORMATION:
4289 trace_header("INFORMATION", dir);
4290 if (dir == DIRECTION_OUT)
4291 add_trace("to", NULL, "CH(%lu)", port_id);
4292 if (dir == DIRECTION_IN)
4293 add_trace("from", NULL, "CH(%lu)", port_id);
4294 add_trace("dialing", NULL, "%s", param->information.id);
4298 case MESSAGE_FACILITY:
4299 trace_header("FACILITY", dir);
4300 if (dir == DIRECTION_OUT)
4301 add_trace("to", NULL, "CH(%lu)", port_id);
4302 if (dir == DIRECTION_IN)
4303 add_trace("from", NULL, "CH(%lu)", port_id);
4308 trace_header("TONE", dir);
4309 if (dir == DIRECTION_OUT)
4310 add_trace("to", NULL, "CH(%lu)", port_id);
4311 if (dir == DIRECTION_IN)
4312 add_trace("from", NULL, "CH(%lu)", port_id);
4313 if (param->tone.name[0])
4315 add_trace("directory", NULL, "%s", param->tone.dir[0]?param->tone.dir:"default");
4316 add_trace("name", NULL, "%s", param->tone.name);
4318 add_trace("off", NULL, NULL);
4322 case MESSAGE_SUSPEND:
4323 case MESSAGE_RESUME:
4324 if (message_type == MESSAGE_SUSPEND)
4325 trace_header("SUSPEND", dir);
4327 trace_header("RESUME", dir);
4328 if (dir == DIRECTION_OUT)
4329 add_trace("to", NULL, "CH(%lu)", port_id);
4330 if (dir == DIRECTION_IN)
4331 add_trace("from", NULL, "CH(%lu)", port_id);
4332 if (param->parkinfo.len)
4333 add_trace("length", NULL, "%d", param->parkinfo.len);
4338 case MESSAGE_BCHANNEL:
4339 trace_header("BCHANNEL", dir);
4340 switch(param->bchannel.type)
4342 case BCHANNEL_REQUEST:
4343 add_trace("type", NULL, "request");
4345 case BCHANNEL_ASSIGN:
4346 add_trace("type", NULL, "assign");
4348 case BCHANNEL_ASSIGN_ACK:
4349 add_trace("type", NULL, "assign_ack");
4351 case BCHANNEL_REMOVE:
4352 add_trace("type", NULL, "remove");
4354 case BCHANNEL_REMOVE_ACK:
4355 add_trace("type", NULL, "remove_ack");
4358 if (param->bchannel.addr)
4359 add_trace("address", NULL, "%x", param->bchannel.addr);
4365 PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message_type);
4369 void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cause, int location, char *display)
4371 struct message *message;
4375 if (!portlist->port_id)
4378 if (!e_connectedmode)
4380 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT);
4381 message->param.disconnectinfo.cause = cause;
4382 message->param.disconnectinfo.location = location;
4384 SCPY(message->param.disconnectinfo.display, display);
4386 SCPY(message->param.disconnectinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4389 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
4391 SCPY(message->param.notifyinfo.display, display);
4393 SCPY(message->param.notifyinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4395 message_put(message);
4396 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);