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) : EndpointApp(epoint)
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 e_ext.rights = 4; /* international */
42 e_ext.rxvol = e_ext.txvol = 256;
43 e_state = EPOINT_STATE_IDLE;
44 e_ext.number[0] = '\0';
45 e_extension_interface[0] = '\0';
46 memset(&e_callerinfo, 0, sizeof(struct caller_info));
47 memset(&e_dialinginfo, 0, sizeof(struct dialing_info));
48 memset(&e_connectinfo, 0, sizeof(struct connect_info));
49 memset(&e_redirinfo, 0, sizeof(struct redir_info));
50 memset(&e_capainfo, 0, sizeof(struct capa_info));
53 e_ruleset = ruleset_main;
55 e_rule = e_ruleset->rule_first;
60 e_match_to_action = NULL;
62 e_extdialing = e_dialinginfo.id;
66 // e_join_tone[0] = e_hold_tone[0] = '\0';
67 e_join_pattern /*= e_hold_pattern*/ = 0;
70 e_adminid = 0; // will be set, if call was initiated via admin socket
75 e_cbdialing[0] = '\0';
78 memset(&e_callbackinfo, 0, sizeof(struct caller_info));
85 e_password_timeout = 0;
86 e_multipoint_cause = 0;
87 e_multipoint_location = 0;
88 e_dialing_queue[0] = '\0';
90 e_crypt_state = CM_ST_NULL;
91 e_crypt_keyengine_busy = 0;
92 e_crypt_info[0] = '\0';
95 e_tx_state = NOTIFY_STATE_ACTIVE;
96 e_rx_state = NOTIFY_STATE_ACTIVE;
97 e_join_cause = e_join_location = 0;
98 /*********************************
99 *********************************
100 ********* ATTENTION *************
101 *********************************
102 *********************************/
103 /* if you add new values, that must be initialized, also check if they must
104 * be initialized when doing callback
110 * EpointAppPBX destructor
112 EndpointAppPBX::~EndpointAppPBX(void)
114 class EndpointAppPBX *temp, **tempp;
118 tempp = &apppbx_first;
128 FATAL("Endpoint not in endpoint's list.\n");
135 * trace header for application
137 void EndpointAppPBX::trace_header(char *name, int direction)
141 char msgtext[sizeof(_trace.name)];
145 /* init trace with given values */
148 numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype),
152 ea_endpoint->ep_serial,
159 /* set new endpoint state
161 void EndpointAppPBX::new_state(int state)
164 if (e_state != state)
166 trace_header("NEW STATE", DIRECTION_NONE);
167 add_trace("state", "old", "%s", state_name[e_state]);
168 add_trace("state", "new", "%s", state_name[state]);
177 * out==0: incomming caller id, out==1: outgoing caller id
179 void EndpointAppPBX::screen(int out, char *id, int idsize, int *type, int *present, struct interface *interface)
182 struct interface_msn *ifmsn;
183 struct interface_screen *ifscreen;
186 /* screen incoming caller id */
189 /* check for MSN numbers, use first MSN if no match */
191 ifmsn = interface->ifmsn;
196 if (!strcmp(ifmsn->msn, id))
204 trace_header("SCREEN (found in MSN list)", DIRECTION_IN);
205 add_trace("msn", NULL, "%s", id);
208 if (!ifmsn && msn1) // not in list, first msn given
210 trace_header("SCREEN (not found MSN in list)", DIRECTION_IN);
211 add_trace("msn", "given", "%s", id);
212 add_trace("msn", "used", "%s", msn1);
214 UNCPY(id, msn1, idsize);
219 /* check screen list */
221 ifscreen = interface->ifscreen_out;
223 ifscreen = interface->ifscreen_in;
226 if (ifscreen->match_type==-1 || ifscreen->match_type==*type)
227 if (ifscreen->match_present==-1 || ifscreen->match_present==*present)
229 if (strchr(ifscreen->match,'%'))
231 if (!strncmp(ifscreen->match, id, strchr(ifscreen->match,'%')-ifscreen->match))
235 if (!strcmp(ifscreen->match, id))
239 ifscreen = ifscreen->next;
241 if (ifscreen) // match
243 trace_header("SCREEN (found in screen list)", out?DIRECTION_OUT:DIRECTION_IN);
246 case INFO_NTYPE_UNKNOWN:
247 add_trace("given", "type", "unknown");
249 case INFO_NTYPE_SUBSCRIBER:
250 add_trace("given", "type", "subscriber");
252 case INFO_NTYPE_NATIONAL:
253 add_trace("given", "type", "national");
255 case INFO_NTYPE_INTERNATIONAL:
256 add_trace("given", "type", "international");
261 case INFO_PRESENT_ALLOWED:
262 add_trace("given", "present", "allowed");
264 case INFO_PRESENT_RESTRICTED:
265 add_trace("given", "present", "restricted");
267 case INFO_PRESENT_NOTAVAIL:
268 add_trace("given", "present", "not available");
271 add_trace("given", "id", "%s", id[0]?id:"<empty>");
272 if (ifscreen->result_type != -1)
274 *type = ifscreen->result_type;
277 case INFO_NTYPE_UNKNOWN:
278 add_trace("used", "type", "unknown");
280 case INFO_NTYPE_SUBSCRIBER:
281 add_trace("used", "type", "subscriber");
283 case INFO_NTYPE_NATIONAL:
284 add_trace("used", "type", "national");
286 case INFO_NTYPE_INTERNATIONAL:
287 add_trace("used", "type", "international");
291 if (ifscreen->result_present != -1)
293 *present = ifscreen->result_present;
296 case INFO_PRESENT_ALLOWED:
297 add_trace("used", "present", "allowed");
299 case INFO_PRESENT_RESTRICTED:
300 add_trace("used", "present", "restricted");
302 case INFO_PRESENT_NOTAVAIL:
303 add_trace("used", "present", "not available");
307 if (strchr(ifscreen->match,'%'))
309 SCPY(suffix, strchr(ifscreen->match,'%') - ifscreen->match + id);
310 UNCPY(id, ifscreen->result, idsize);
312 if (strchr(ifscreen->result,'%'))
314 *strchr(ifscreen->result,'%') = '\0';
315 UNCAT(id, suffix, idsize);
320 UNCPY(id, ifscreen->result, idsize);
323 add_trace("used", "id", "%s", id[0]?id:"<empty>");
328 /* release join and port (as specified)
330 void EndpointAppPBX::release(int release, int joinlocation, int joincause, int portlocation, int portcause)
332 struct port_list *portlist;
333 struct message *message;
336 /* message to test call */
337 admin_call_response(e_adminid, ADMIN_CALL_RELEASE, "", joincause, joinlocation, 0);
339 /* if a release is pending */
340 if (release==RELEASE_JOIN || release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY)
342 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): do pending release (joincause %d location %d)\n", ea_endpoint->ep_serial, joincause, joinlocation);
343 if (ea_endpoint->ep_join_id)
345 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_RELEASE);
346 message->param.disconnectinfo.cause = joincause;
347 message->param.disconnectinfo.location = joinlocation;
348 message_put(message);
349 ea_endpoint->ep_join_id = 0;
353 if (release != RELEASE_PORT_JOINONLY)
356 join_release(e_hold_id, ea_endpoint->ep_serial, 1, joinlocation, joincause);
361 if (release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY)
363 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release (portcause %d portlocation)\n", ea_endpoint->ep_serial, portcause, portlocation);
364 while((portlist = ea_endpoint->ep_portlist))
366 if (portlist->port_id)
368 SPRINT(cause, "cause_%02x", portcause);
369 set_tone(portlist, cause);
370 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
371 message->param.disconnectinfo.cause = portcause;
372 message->param.disconnectinfo.location = portlocation;
373 message_put(message);
374 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
376 ea_endpoint->free_portlist(portlist);
379 /* if callback is enabled, call back with the given caller id */
382 /* reset some stuff */
383 new_state(EPOINT_STATE_IDLE);
384 memset(&e_connectinfo, 0, sizeof(struct connect_info));
385 memset(&e_redirinfo, 0, sizeof(struct redir_info));
386 e_start = e_stop = 0;
387 e_ruleset = ruleset_main;
389 e_rule = e_ruleset->rule_first;
391 e_action_timeout = 0;
393 e_match_to_action = NULL;
395 e_extdialing = e_dialinginfo.id;
402 e_multipoint_cause = 0;
403 e_multipoint_location = 0;
404 e_dialing_queue[0] = '\0';
406 e_crypt_state = CM_ST_NULL;
407 e_crypt_keyengine_busy = 0;
408 e_crypt_info[0] = '\0';
412 e_tx_state = NOTIFY_STATE_ACTIVE;
413 e_rx_state = NOTIFY_STATE_ACTIVE;
414 e_join_cause = e_join_location = 0;
416 /* the caller info of the callback user */
417 memcpy(&e_callbackinfo, &e_callerinfo, sizeof(e_callbackinfo));
418 memset(&e_dialinginfo, 0, sizeof(e_dialinginfo));
419 /* create dialing by callerinfo */
420 if (e_ext.number[0] && e_extension_interface[0])
422 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to internal: %s interface %s\n", ea_endpoint->ep_serial, e_ext.number, e_extension_interface);
423 /* create callback to the current terminal */
424 SCPY(e_dialinginfo.id, e_ext.number);
425 SCPY(e_dialinginfo.interfaces, e_extension_interface);
426 e_dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
427 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
432 SCPY(e_dialinginfo.id, e_cbto);
435 /* numberrize caller id and use it to dial to the callback */
436 SCPY(e_dialinginfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype));
438 e_dialinginfo.itype = INFO_ITYPE_ISDN;
439 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
440 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to external: %s\n", ea_endpoint->ep_serial, e_dialinginfo.id);
445 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release of epoint itself.\n", ea_endpoint->ep_serial);
446 ea_endpoint->ep_use--; /* when e_lock is 0, the endpoint will be deleted */
452 /* cancel callerid if restricted, unless anon-ignore is enabled at extension or port is of type external (so called police gets caller id :)*/
453 void apply_callerid_restriction(int anon_ignore, char *id, int *ntype, int *present, int *screen, char *extension, char *name)
455 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");
457 /* caller id is not restricted, so we do nothing */
458 if (*present != INFO_PRESENT_RESTRICTED)
461 /* only extensions are restricted */
467 /* if we enabled anonymouse ignore */
471 /* else we remove the caller id */
475 *ntype = INFO_NTYPE_UNKNOWN;
477 // *screen = INFO_SCREEN_USER;
478 // maybe we should not make voip address anonymous
481 // maybe it's no fraud to present extension id
483 // extension[0] = '\0';
488 /* used display message to display callerid as available */
489 char *EndpointAppPBX::apply_callerid_display(char *id, int itype, int ntype, int present, int screen, char *extension, char *name)
491 static char display[81];
494 char *cid = numberrize_callerinfo(id, ntype);
496 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");
505 /* NOTE: is caller is is not available for this extesion, it has been removed by apply_callerid_restriction already */
507 /* internal extension's caller id */
508 if (extension[0] && e_ext.display_int)
511 SCAT(display, extension);
514 if (itype == INFO_ITYPE_VBOX)
515 SCAT(display, "(vbox)");
517 SCAT(display, "(int)");
520 /* external caller id */
521 if (!extension[0] && e_ext.display_ext)
527 if (present == INFO_PRESENT_RESTRICTED)
528 SCAT(display, "anonymous");
530 SCAT(display, "unknown");
537 /* display if callerid is anonymouse but available due anon-ignore */
538 if (e_ext.display_anon && present==INFO_PRESENT_RESTRICTED)
541 SCAT(display, "unknown");
544 SCAT(display, " anon");
547 /* display if callerid is anonymouse but available due anon-ignore */
548 if (e_ext.display_fake && screen==INFO_SCREEN_USER && present!=INFO_PRESENT_NULL)
554 if (present == INFO_PRESENT_RESTRICTED)
555 SCAT(display, "anonymous");
557 SCAT(display, "unknown");
562 SCAT(display, " fake");
566 if (name[0] && e_ext.display_name)
568 if (!display[0] && cid[0])
579 * uses the current state to notify activity
581 void EndpointAppPBX::notify_active(void)
583 struct port_list *portlist = ea_endpoint->ep_portlist;
584 struct message *message;
589 case NOTIFY_STATE_ACTIVE:
590 /* we are already active, so we don't do anything */
593 case NOTIFY_STATE_SUSPEND:
594 notify = INFO_NOTIFY_USER_RESUMED;
597 set_tone(portlist, NULL);
598 portlist = portlist->next;
600 portlist = ea_endpoint->ep_portlist;
603 case NOTIFY_STATE_HOLD:
604 notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
607 set_tone(portlist, NULL);
608 portlist = portlist->next;
610 portlist = ea_endpoint->ep_portlist;
613 case NOTIFY_STATE_CONFERENCE:
614 notify = INFO_NOTIFY_CONFERENCE_DISCONNECTED;
617 set_tone(portlist, NULL);
618 portlist = portlist->next;
620 portlist = ea_endpoint->ep_portlist;
624 PERROR("unknown e_tx_state = %d\n", e_tx_state);
630 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
631 message->param.notifyinfo.notify = notify;
632 message_put(message);
633 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
634 portlist = portlist->next;
640 * keypad functions during call. one example to use this is to put a call on hold or start a conference
642 void EndpointAppPBX::keypad_function(char digit)
645 /* we must be in a call, in order to send messages to the call */
646 if (e_ext.number[0] == '\0')
648 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) IGNORING keypad received not from extension.\n", ea_endpoint->ep_serial);
654 /* join conference */
656 if (ea_endpoint->ep_join_id == 0)
658 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad received during connect but not during a call.\n", ea_endpoint->ep_serial);
661 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join call with call on hold\n", ea_endpoint->ep_serial);
667 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) shared key encryption selected.\n", ea_endpoint->ep_serial);
671 /* crypt key-exchange */
673 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) key exchange encryption selected.\n", ea_endpoint->ep_serial);
679 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) encryption off selected.\n", ea_endpoint->ep_serial);
684 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) unsupported keypad digit '%c'.\n", ea_endpoint->ep_serial, digit);
689 /* set tone pattern for port */
690 void EndpointAppPBX::set_tone(struct port_list *portlist, char *tone)
692 struct message *message;
697 /* store for suspended processes */
701 if (e_join_pattern /* pattern are provided */
702 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_SETUP)
703 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_OVERLAP)
704 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_IN_PROCEEDING)
705 && !(e_ext.own_alerting && e_state == EPOINT_STATE_IN_ALERTING)
706 && !(e_ext.own_cause && e_state == EPOINT_STATE_IN_DISCONNECT)
707 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_SETUP)
708 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_OVERLAP)
709 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_OUT_PROCEEDING)
710 && !(e_ext.own_alerting && e_state == EPOINT_STATE_OUT_ALERTING)
711 && !(e_ext.own_cause && e_state == EPOINT_STATE_OUT_DISCONNECT)
712 && tone[0] && !!strncmp(tone,"crypt_*",6))
714 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) tone not provided since patterns are available\n", ea_endpoint->ep_serial);
720 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_TONE);
721 SCPY(message->param.tone.dir, e_ext.tones_dir[0]?e_ext.tones_dir:options.tones_dir);
722 SCPY(message->param.tone.name, tone);
723 message_put(message);
724 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
727 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port to notify tone.\n", ea_endpoint->ep_serial);
734 * hunts an mISDNport that is available for an outgoing call
735 * if no ifname was given, any interface that is not an extension
738 struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel)
740 struct interface *interface;
741 struct interface_port *ifport, *ifport_start;
742 struct select_channel *selchannel;
743 struct mISDNport *mISDNport;
746 interface = interface_first;
748 /* first find the given interface or, if not given, one with no extension */
753 /* check for given interface */
756 if (!strcasecmp(interface->name, ifname))
758 /* found explicit interface */
759 trace_header("CHANNEL SELECTION (found interface)", DIRECTION_NONE);
760 add_trace("interface", NULL, "%s", ifname);
767 if (!interface->extension)
769 /* found non extension */
770 trace_header("CHANNEL SELECTION (found non extension interface)", DIRECTION_NONE);
771 add_trace("interface", NULL, "%s", interface->name);
777 interface = interface->next;
781 /* see if interface has ports */
782 if (!interface->ifport)
785 trace_header("CHANNEL SELECTION (interface has no active ports, skipping)", DIRECTION_NONE);
786 add_trace("interface", NULL, "%s", interface->name);
788 interface = interface->next;
792 /* select port by algorithm */
793 ifport_start = interface->ifport;
795 if (interface->hunt == HUNT_ROUNDROBIN)
797 while(ifport_start->next && index<interface->hunt_next)
799 ifport_start = ifport_start->next;
802 trace_header("CHANNEL SELECTION (starting round-robin)", DIRECTION_NONE);
803 add_trace("port", NULL, "%d", ifport_start->portnum);
804 add_trace("position", NULL, "%d", index);
809 ifport = ifport_start;
812 /* see if port is available */
813 if (!ifport->mISDNport)
815 trace_header("CHANNEL SELECTION (port not available, skipping)", DIRECTION_NONE);
816 add_trace("port", NULL, "%d", ifport->portnum);
817 add_trace("position", NULL, "%d", index);
821 mISDNport = ifport->mISDNport;
823 /* see if port is administratively blocked */
826 trace_header("CHANNEL SELECTION (port blocked by admin, skipping)", DIRECTION_NONE);
827 add_trace("port", NULL, "%d", ifport->portnum);
828 add_trace("position", NULL, "%d", index);
833 /* see if link is up on PTP*/
834 if (mISDNport->ptp && !mISDNport->l2link)
836 trace_header("CHANNEL SELECTION (port is ptp with layer 2 down, skipping)", DIRECTION_NONE);
837 add_trace("port", NULL, "%d", ifport->portnum);
838 add_trace("position", NULL, "%d", index);
843 /* check for channel form selection list */
845 selchannel = ifport->out_channel;
848 switch(selchannel->channel)
850 case CHANNEL_FREE: /* free channel */
851 if (mISDNport->b_reserved >= mISDNport->b_num)
852 break; /* all channel in use or reserverd */
855 while(i < mISDNport->b_num)
857 if (mISDNport->b_port[i] == NULL)
859 *channel = i+1+(i>=15);
860 trace_header("CHANNEL SELECTION (selecting free channel)", DIRECTION_NONE);
861 add_trace("port", NULL, "%d", ifport->portnum);
862 add_trace("position", NULL, "%d", index);
863 add_trace("channel", NULL, "%d", *channel);
869 trace_header("CHANNEL SELECTION (no channel is 'free')", DIRECTION_NONE);
870 add_trace("port", NULL, "%d", ifport->portnum);
871 add_trace("position", NULL, "%d", index);
875 case CHANNEL_ANY: /* don't ask for channel */
876 if (mISDNport->b_reserved >= mISDNport->b_num)
878 trace_header("CHANNEL SELECTION (cannot ask for 'any' channel, all reserved)", DIRECTION_NONE);
879 add_trace("port", NULL, "%d", ifport->portnum);
880 add_trace("position", NULL, "%d", index);
881 add_trace("total", NULL, "%d", mISDNport->b_num);
882 add_trace("reserved", NULL, "%d", mISDNport->b_reserved);
884 break; /* all channel in use or reserverd */
886 trace_header("CHANNEL SELECTION (using 'any' channel)", DIRECTION_NONE);
887 add_trace("port", NULL, "%d", ifport->portnum);
888 add_trace("position", NULL, "%d", index);
890 *channel = CHANNEL_ANY;
893 case CHANNEL_NO: /* call waiting */
894 trace_header("CHANNEL SELECTION (using 'no' channel, call-waiting)", DIRECTION_NONE);
895 add_trace("port", NULL, "%d", ifport->portnum);
896 add_trace("position", NULL, "%d", index);
898 *channel = CHANNEL_NO;
902 if (selchannel->channel<1 || selchannel->channel==16)
904 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
905 add_trace("port", NULL, "%d", ifport->portnum);
906 add_trace("position", NULL, "%d", index);
907 add_trace("channel", NULL, "%d", selchannel->channel);
909 break; /* invalid channels */
911 i = selchannel->channel-1-(selchannel->channel>=17);
912 if (i >= mISDNport->b_num)
914 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
915 add_trace("port", NULL, "%d", ifport->portnum);
916 add_trace("position", NULL, "%d", index);
917 add_trace("channel", NULL, "%d", selchannel->channel);
918 add_trace("channels", NULL, "%d", mISDNport->b_num);
920 break; /* channel not in port */
922 if (mISDNport->b_port[i] == NULL)
924 *channel = selchannel->channel;
925 trace_header("CHANNEL SELECTION (selecting given channel)", DIRECTION_NONE);
926 add_trace("port", NULL, "%d", ifport->portnum);
927 add_trace("position", NULL, "%d", index);
928 add_trace("channel", NULL, "%d", *channel);
935 break; /* found channel */
936 selchannel = selchannel->next;
939 /* if channel was found, return mISDNport and channel */
942 /* setting next port to start next time */
943 if (interface->hunt == HUNT_ROUNDROBIN)
948 interface->hunt_next = index;
954 trace_header("CHANNEL SELECTION (skipping, no channel found)", DIRECTION_NONE);
955 add_trace("port", NULL, "%d", ifport->portnum);
956 add_trace("position", NULL, "%d", index);
960 /* go next port, until all ports are checked */
962 ifport = ifport->next;
966 ifport = interface->ifport;
968 if (ifport != ifport_start)
971 return(NULL); /* no port found */
974 /* outgoing setup to port(s)
975 * ports will be created and a setup is sent if everything is ok. otherwhise
976 * the endpoint is destroyed.
978 void EndpointAppPBX::out_setup(void)
980 struct dialing_info dialinginfo;
982 // class pdss1 *pdss1;
983 struct port_list *portlist;
984 struct message *message;
986 int cause = CAUSE_RESSOURCEUNAVAIL;
989 struct mISDNport *mISDNport;
992 class EndpointAppPBX *atemp;
993 // char allowed_ports[256];
995 char ifname[sizeof(e_ext.interfaces)],
997 struct port_settings port_settings;
1001 /* create settings for creating port */
1002 memset(&port_settings, 0, sizeof(port_settings));
1003 if (e_ext.tones_dir)
1004 SCPY(port_settings.tones_dir, e_ext.tones_dir);
1006 SCPY(port_settings.tones_dir, options.tones_dir);
1007 port_settings.tout_setup = e_ext.tout_setup;
1008 port_settings.tout_dialing = e_ext.tout_dialing;
1009 port_settings.tout_proceeding = e_ext.tout_proceeding;
1010 port_settings.tout_alerting = e_ext.tout_alerting;
1011 port_settings.tout_disconnect = e_ext.tout_disconnect;
1012 // port_settings.tout_hold = e_ext.tout_hold;
1013 // port_settings.tout_park = e_ext.tout_park;
1014 port_settings.no_seconds = e_ext.no_seconds;
1016 /* 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 */
1018 /* check what dialinginfo.itype we got */
1019 switch(e_dialinginfo.itype)
1021 /* *********************** call to extension or vbox */
1022 case INFO_ITYPE_ISDN_EXTENSION:
1023 /* check if we deny incoming calls when we use an extension */
1024 if (e_ext.noknocking)
1026 atemp = apppbx_first;
1030 if (!strcmp(atemp->e_ext.number, e_ext.number))
1032 atemp = atemp->next;
1036 PERROR("EPOINT(%d) noknocking and currently a call\n", ea_endpoint->ep_serial);
1037 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYSPE_ join, port */
1038 return; /* must exit here */
1041 /* FALL THROUGH !!!! */
1042 case INFO_ITYPE_VBOX:
1043 /* get dialed extension's info */
1044 // SCPY(exten, e_dialinginfo.id);
1045 // if (strchr(exten, ','))
1046 // *strchr(exten, ',') = '\0';
1047 // if (!read_extension(&e_ext, exten))
1048 if (!read_extension(&e_ext, e_dialinginfo.id))
1050 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) extension %s not configured\n", ea_endpoint->ep_serial, e_dialinginfo.id);
1051 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1052 return; /* must exit here */
1055 if (e_dialinginfo.itype == INFO_ITYPE_VBOX)
1057 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing directly to VBOX\n", ea_endpoint->ep_serial);
1062 /* string from unconditional call forward (cfu) */
1066 /* present to forwarded party */
1067 if (e_ext.anon_ignore && e_callerinfo.id[0])
1069 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1071 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
1075 /* string from busy call forward (cfb) */
1079 class EndpointAppPBX *checkapp = apppbx_first;
1082 if (checkapp != this) /* any other endpoint except our own */
1084 if (!strcmp(checkapp->e_ext.number, e_ext.number))
1086 /* present to forwarded party */
1087 if (e_ext.anon_ignore && e_callerinfo.id[0])
1089 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1091 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
1095 checkapp = checkapp->next;
1099 /* string from no-response call forward (cfnr) */
1103 /* when cfnr is done, out_setup() will setup the call */
1106 /* present to forwarded party */
1107 if (e_ext.anon_ignore && e_callerinfo.id[0])
1109 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1113 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
1115 e_cfnr_release = now + e_ext.cfnr_delay;
1116 e_cfnr_call = now + e_ext.cfnr_delay + 1; /* call one second after release */
1117 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);
1121 /* call to all internal interfaces */
1122 p = e_ext.interfaces;
1123 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) generating multiple joins for extension %s to interfaces %s\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
1127 while(*p!=',' && *p!='\0')
1129 SCCAT(ifname, *p++);
1132 /* found interface */
1133 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
1134 /* hunt for mISDNport and create Port */
1135 mISDNport = hunt_port(ifname, &channel);
1138 trace_header("INTERFACE (not found or busy)", DIRECTION_NONE);
1139 add_trace("interface", NULL, "%s", ifname);
1143 /* creating INTERNAL port */
1144 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1145 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force);
1147 FATAL("No memory for DSS1 Port instance\n");
1148 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
1149 memset(&dialinginfo, 0, sizeof(dialinginfo));
1150 SCPY(dialinginfo.id, e_dialinginfo.id);
1151 dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
1152 dialinginfo.ntype = e_dialinginfo.ntype;
1153 /* create port_list relation */
1154 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
1157 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1159 goto check_anycall_intern;
1161 /* directory.list */
1162 if (e_callerinfo.id[0] && (e_ext.centrex || e_ext.display_name))
1164 dirname = parse_directory(e_callerinfo.id, e_callerinfo.ntype);
1166 SCPY(e_callerinfo.name, dirname);
1168 // dss1 = (class Pdss1 *)port;
1170 //printf("INTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1171 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1172 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1173 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1174 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1175 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1176 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1177 //terminal if (e_dialinginfo.id)
1178 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1179 /* handle restricted caller ids */
1180 apply_callerid_restriction(e_ext.anon_ignore, 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);
1181 apply_callerid_restriction(e_ext.anon_ignore, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, 0, message->param.setup.redirinfo.extension, NULL);
1182 /* display callerid if desired for extension */
1183 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));
1184 //printf("\n\ndisplay = %s\n\n\n",message->param.setup.callerinfo.display);
1185 /* use cnip, if enabld */
1187 message->param.setup.callerinfo.name[0] = '\0';
1188 /* screen clip if prefix is required */
1189 if (message->param.setup.callerinfo.id[0] && e_ext.clip_prefix[0])
1191 SCPY(message->param.setup.callerinfo.id, e_ext.clip_prefix);
1192 SCAT(message->param.setup.callerinfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype));
1193 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1195 /* use internal caller id */
1196 if (e_callerinfo.extension[0] && (message->param.setup.callerinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
1198 SCPY(message->param.setup.callerinfo.id, e_callerinfo.extension);
1199 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1201 message_put(message);
1202 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1206 /* string from parallel call forward (cfp) */
1210 if (e_ext.anon_ignore && e_callerinfo.id[0])
1212 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1216 vbox_only: /* entry point for answering machine only */
1217 cfu_only: /* entry point for cfu */
1218 cfb_only: /* entry point for cfb */
1219 cfnr_only: /* entry point for cfnr */
1220 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call extension %s for external destiantion(s) '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
1225 /* only if vbox should be dialed, and terminal is given */
1226 if (!strcmp(p, "vbox") && e_ext.number[0])
1228 /* go to the end of p */
1231 /* answering vbox call */
1232 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) answering machine\n", ea_endpoint->ep_serial);
1234 if (!(port = new VBoxPort(PORT_TYPE_VBOX_OUT, &port_settings)))
1235 FATAL("No memory for VBOX Port instance\n");
1236 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocated port %s\n", ea_endpoint->ep_serial, port->p_name);
1237 UCPY(cfp, e_ext.number); /* cfp or any other direct forward/vbox */
1241 while(*p!=',' && *p!='\0')
1246 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cfp external %s\n", ea_endpoint->ep_serial, cfp);
1247 /* hunt for mISDNport and create Port */
1248 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1251 /* creating EXTERNAL port*/
1252 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1253 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)))
1254 FATAL("No memory for DSS1 Port instance\n");
1255 earlyb = mISDNport->earlyb;
1259 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1260 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1266 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port found or created, which is idle.\n", ea_endpoint->ep_serial);
1267 goto check_anycall_intern;
1269 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found or created port %s\n", ea_endpoint->ep_serial, port->p_name);
1270 memset(&dialinginfo, 0, sizeof(dialinginfo));
1271 SCPY(dialinginfo.id, cfp);
1272 dialinginfo.itype = INFO_ITYPE_ISDN;
1273 dialinginfo.ntype = e_dialinginfo.ntype;
1274 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
1277 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1279 goto check_anycall_intern;
1281 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1282 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1283 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1284 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1285 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1286 /* if clip is hidden */
1287 if (e_ext.clip==CLIP_HIDE && port->p_type!=PORT_TYPE_VBOX_OUT)
1289 SCPY(message->param.setup.callerinfo.id, e_ext.callerid);
1290 SCPY(message->param.setup.callerinfo.extension, e_ext.number);
1291 message->param.setup.callerinfo.ntype = e_ext.callerid_type;
1292 message->param.setup.callerinfo.present = e_ext.callerid_present;
1294 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1295 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1296 //terminal if (e_dialinginfo.id)
1297 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1298 /* handle restricted caller ids */
1299 apply_callerid_restriction(e_ext.anon_ignore, 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);
1300 apply_callerid_restriction(e_ext.anon_ignore, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, 0, message->param.setup.redirinfo.extension, NULL);
1301 /* display callerid if desired for extension */
1302 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));
1303 message_put(message);
1304 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1308 check_anycall_intern:
1309 /* now we have all ports created */
1312 trace_header("INTERFACE (no extension's interface)", DIRECTION_NONE);
1314 if (!ea_endpoint->ep_join_id)
1316 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1317 return; /* must exit here */
1321 /* *********************** external call */
1323 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id);
1324 /* call to extenal interfaces */
1325 p = e_dialinginfo.id;
1329 while(*p!=',' && *p!='\0')
1330 SCCAT(number, *p++);
1334 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");
1335 /* hunt for mISDNport and create Port */
1336 /* hunt for mISDNport and create Port */
1337 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1340 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1341 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1343 goto check_anycall_extern;
1345 /* creating EXTERNAL port*/
1346 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1347 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)))
1348 FATAL("No memory for DSS1 Port instance\n");
1349 earlyb = mISDNport->earlyb;
1350 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
1351 memset(&dialinginfo, 0, sizeof(dialinginfo));
1352 SCPY(dialinginfo.id, number);
1353 dialinginfo.itype = INFO_ITYPE_ISDN;
1354 dialinginfo.ntype = e_dialinginfo.ntype;
1355 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
1358 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1360 goto check_anycall_extern;
1362 // dss1 = (class Pdss1 *)port;
1363 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1364 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1365 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1366 SCPY(message->param.setup.dialinginfo.id, number);
1367 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1368 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1369 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1370 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1371 //terminal if (e_dialinginfo.id)
1372 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1373 /* handle restricted caller ids */
1374 apply_callerid_restriction(e_ext.anon_ignore, 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);
1375 apply_callerid_restriction(e_ext.anon_ignore, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, 0, message->param.setup.redirinfo.extension, NULL);
1376 /* display callerid if desired for extension */
1377 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));
1378 message_put(message);
1379 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1383 check_anycall_extern:
1384 /* now we have all ports created */
1387 trace_header("INTERFACE (no free ports found)", DIRECTION_NONE);
1389 if (!ea_endpoint->ep_join_id)
1391 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1392 return; /* must exit here */
1400 /* handler for endpoint
1404 int EndpointAppPBX::handler(void)
1406 if (e_crypt_state!=CM_ST_NULL)
1411 /* process answering machine (play) handling */
1414 if (e_action->index == ACTION_VBOX_PLAY)
1417 /* process action timeout */
1418 if (e_action_timeout)
1419 if (now_d >= e_action_timeout)
1421 if (e_state!=EPOINT_STATE_CONNECT)
1424 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current action timed out.\n", ea_endpoint->ep_serial);
1425 e_multipoint_cause = 0;
1426 e_multipoint_location = 0;
1427 new_state(EPOINT_STATE_IN_OVERLAP);
1430 return(1); /* we must exit, because our endpoint might be gone */
1432 e_action_timeout = 0;
1435 /* process action timeout */
1436 if (e_match_timeout)
1437 if (now_d >= e_match_timeout)
1440 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we got a match timeout.\n", ea_endpoint->ep_serial);
1442 return(1); /* we must exit, because our endpoint might be gone */
1447 /* process redialing (epoint redials to port) */
1450 if (now_d >= e_redial)
1453 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial.\n", ea_endpoint->ep_serial);
1455 new_state(EPOINT_STATE_OUT_SETUP);
1456 /* call special setup routine */
1463 /* process powerdialing (epoint redials to epoint) */
1464 if (e_powerdialing > 0)
1466 if (now_d >= e_powerdialing)
1468 e_powerdialing = -1; /* leave power dialing on */
1469 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial of powerdial.\n", ea_endpoint->ep_serial);
1472 e_ruleset = ruleset_main;
1474 e_rule = e_ruleset->rule_first;
1476 new_state(EPOINT_STATE_IN_OVERLAP);
1482 /* process call forward no response */
1485 struct port_list *portlist;
1486 struct message *message;
1488 if (now >= e_cfnr_release)
1490 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-no-response time has expired, hanging up.\n", ea_endpoint->ep_serial);
1493 /* release all ports */
1494 while((portlist = ea_endpoint->ep_portlist))
1496 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1497 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
1498 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1499 message_put(message);
1500 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1501 ea_endpoint->free_portlist(portlist);
1504 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1505 message->param.audiopath = CHANNEL_STATE_HOLD;
1506 message_put(message);
1507 /* indicate no patterns */
1508 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1509 message_put(message);
1510 /* set setup state, since we have no response from the new join */
1511 new_state(EPOINT_STATE_OUT_SETUP);
1516 if (now >= e_cfnr_call)
1518 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-busy time has expired, calling the forwarded number: %s.\n", ea_endpoint->ep_serial, e_ext.cfnr);
1524 /* handle connection to user */
1525 if (e_state == EPOINT_STATE_IDLE)
1527 /* epoint is idle, check callback */
1529 if (now_d >= e_callback)
1531 e_callback = 0; /* done with callback */
1532 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting callback.\n", ea_endpoint->ep_serial);
1533 new_state(EPOINT_STATE_OUT_SETUP);
1539 /* check for password timeout */
1541 if (e_action->index==ACTION_PASSWORD || e_action->index==ACTION_PASSWORD_WRITE)
1543 struct port_list *portlist;
1545 if (now >= e_password_timeout)
1547 e_ruleset = ruleset_main;
1549 e_rule = e_ruleset->rule_first;
1551 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) password timeout %s\n", ea_endpoint->ep_serial, e_extdialing);
1552 trace_header("PASSWORD timeout", DIRECTION_NONE);
1554 e_connectedmode = 0;
1556 new_state(EPOINT_STATE_OUT_DISCONNECT);
1557 portlist = ea_endpoint->ep_portlist;
1560 message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
1561 set_tone(portlist, "cause_10");
1571 /* doing a hookflash */
1572 void EndpointAppPBX::hookflash(void)
1576 /* be sure that we are active */
1578 e_tx_state = NOTIFY_STATE_ACTIVE;
1580 trace_header("HOOKFLASH DTMF", DIRECTION_NONE);
1582 if (ea_endpoint->ep_use > 1)
1584 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot hooflash while child process is running.\n", ea_endpoint->ep_serial);
1587 /* dialtone after pressing the hash key */
1588 process_hangup(e_join_cause, e_join_location);
1589 e_multipoint_cause = 0;
1590 e_multipoint_location = 0;
1591 port = find_port_id(ea_endpoint->ep_portlist->port_id);
1594 port->set_echotest(0);
1596 if (ea_endpoint->ep_join_id)
1598 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1600 e_ruleset = ruleset_main;
1602 e_rule = e_ruleset->rule_first;
1604 new_state(EPOINT_STATE_IN_OVERLAP);
1605 e_connectedmode = 1;
1606 SCPY(e_dialinginfo.id, e_ext.prefix);
1607 e_extdialing = e_dialinginfo.id;
1609 if (e_dialinginfo.id[0])
1611 set_tone(ea_endpoint->ep_portlist, "dialing");
1615 set_tone(ea_endpoint->ep_portlist, "dialpbx");
1622 /* messages from port
1624 /* port MESSAGE_SETUP */
1625 void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, union parameter *param)
1627 struct message *message;
1629 int writeext; /* flags need to write extension after modification */
1631 struct interface *interface;
1633 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1635 portlist->port_type = param->setup.port_type;
1636 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
1637 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
1638 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
1639 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
1640 e_dtmf = param->setup.dtmf;
1641 /* screen incoming caller id */
1642 interface = interface_first;
1645 if (!strcmp(e_callerinfo.interface, interface->name))
1649 interface = interface->next;
1652 screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface);
1654 /* process extension */
1655 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1657 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is extension\n", ea_endpoint->ep_serial);
1658 /* port makes call from extension */
1659 SCPY(e_callerinfo.extension, e_callerinfo.id);
1660 SCPY(e_ext.number, e_callerinfo.extension);
1661 SCPY(e_extension_interface, e_callerinfo.interface);
1664 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is external or voip\n", ea_endpoint->ep_serial);
1667 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1669 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1671 /* get extension's info about caller */
1672 if (!read_extension(&e_ext, e_ext.number))
1674 /* extension doesn't exist */
1675 trace_header("EXTENSION (not created)", DIRECTION_IN);
1676 add_trace("extension", NULL, "%s", e_ext.number);
1678 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
1679 new_state(EPOINT_STATE_OUT_DISCONNECT);
1680 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
1681 e_ext.number[0] = '\0'; /* no terminal */
1686 /* put prefix (next) in front of e_dialinginfo.id */
1689 SPRINT(buffer, "%s%s", e_ext.next, e_dialinginfo.id);
1690 SCPY(e_dialinginfo.id, buffer);
1691 e_ext.next[0] = '\0';
1693 } else if (e_ext.prefix[0])
1695 SPRINT(buffer, "%s%s", e_ext.prefix, e_dialinginfo.id);
1696 SCPY(e_dialinginfo.id, buffer);
1699 /* screen caller id by extension's config */
1700 e_callerinfo.screen = INFO_SCREEN_NETWORK;
1702 SCPY(e_callerinfo.name, e_ext.name);
1703 /* use caller id (or if exist: id_next_call) for this call */
1704 if (e_ext.id_next_call_present >= 0)
1706 SCPY(e_callerinfo.id, e_ext.id_next_call);
1707 /* if we restrict the pesentation */
1708 if (e_ext.id_next_call_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1709 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1710 else e_callerinfo.present = e_ext.id_next_call_present;
1711 e_callerinfo.ntype = e_ext.id_next_call_type;
1712 e_ext.id_next_call_present = -1;
1716 SCPY(e_callerinfo.id, e_ext.callerid);
1717 /* if we restrict the pesentation */
1718 if (e_ext.callerid_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1719 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1720 else e_callerinfo.present = e_ext.callerid_present;
1721 e_callerinfo.ntype = e_ext.callerid_type;
1724 /* extension is written */
1726 write_extension(&e_ext, e_ext.number);
1728 /* set volume of rx and tx */
1729 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1730 if (e_ext.txvol!=256 || e_ext.rxvol!=256)
1732 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
1733 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
1734 message->param.mISDNsignal.rxvol = e_ext.txvol;
1735 message->param.mISDNsignal.txvol = e_ext.rxvol;
1736 message_put(message);
1739 /* start recording if enabled */
1740 if (e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO))
1742 /* check if we are a terminal */
1743 if (e_ext.number[0] == '\0')
1744 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
1747 port = find_port_id(portlist->port_id);
1749 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
1754 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from external port\n", ea_endpoint->ep_serial);
1755 /* no terminal identification */
1756 e_ext.number[0] = '\0';
1757 e_extension_interface[0] = '\0';
1758 memset(&e_ext, 0, sizeof(e_ext));
1759 e_ext.rights = 4; /* right to dial internat */
1763 e_ruleset = ruleset_main;
1765 e_rule = e_ruleset->rule_first;
1767 e_extdialing = e_dialinginfo.id;
1768 new_state(EPOINT_STATE_IN_SETUP);
1769 if (e_dialinginfo.id[0])
1771 set_tone(portlist, "dialing");
1774 if (e_ext.number[0])
1775 set_tone(portlist, "dialpbx");
1777 set_tone(portlist, "dialtone");
1780 if (e_state == EPOINT_STATE_IN_SETUP)
1782 /* request MORE info, if not already at higher state */
1783 new_state(EPOINT_STATE_IN_OVERLAP);
1784 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_OVERLAP);
1785 message_put(message);
1786 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1790 /* port MESSAGE_INFORMATION */
1791 void EndpointAppPBX::port_information(struct port_list *portlist, int message_type, union parameter *param)
1793 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1797 /* turn off dtmf detection, in case dtmf is sent with keypad information */
1800 trace_header("DTMF (disabling due to keypad)", DIRECTION_IN);
1805 /* if vbox_play is done, the information are just used as they come */
1807 if (e_action->index == ACTION_VBOX_PLAY)
1809 /* concat dialing string */
1810 SCAT(e_dialinginfo.id, param->information.id);
1815 /* keypad when disconnect but in connected mode */
1816 if (e_state==EPOINT_STATE_OUT_DISCONNECT && e_connectedmode)
1818 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received after disconnect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1819 /* processing keypad function */
1820 if (param->information.id[0] == '0')
1827 /* keypad when connected */
1828 if (e_state == EPOINT_STATE_CONNECT)
1832 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1833 /* processing keypad function */
1834 if (param->information.id[0] == '0')
1838 if (param->information.id[0])
1839 keypad_function(param->information.id[0]);
1842 trace_header("DTMF (not enabled by extension's settings)", DIRECTION_IN);
1847 if (e_state != EPOINT_STATE_IN_OVERLAP)
1849 trace_header("DTMF (ignored, not connected and not dialing)", DIRECTION_IN);
1853 if (!param->information.id[0])
1855 if (e_dialinginfo.id[0]=='\0' && !e_action)
1857 set_tone(portlist, "dialing");
1860 if (e_action->index==ACTION_OUTDIAL
1861 || e_action->index==ACTION_EXTERNAL)
1864 set_tone(portlist, "dialing");
1865 else if (!e_extdialing[0])
1866 set_tone(portlist, "dialing");
1868 /* concat dialing string */
1869 SCAT(e_dialinginfo.id, param->information.id);
1873 /* port MESSAGE_DTMF */
1874 void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
1876 /* only if dtmf detection is enabled */
1879 trace_header("DTMF (disabled)", DIRECTION_IN);
1883 trace_header("DTMF", DIRECTION_IN);
1884 add_trace("digit", NULL, "%c", param->dtmf);
1888 NOTE: vbox is now handled due to overlap state
1889 /* if vbox_play is done, the dtmf digits are just used as they come */
1891 if (e_action->index == ACTION_VBOX_PLAY)
1893 /* concat dialing string */
1894 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id))
1896 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1897 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1900 /* continue to process *X# sequences */
1904 /* check for *X# sequence */
1905 if (e_state == EPOINT_STATE_CONNECT)
1907 if (e_dtmf_time+3 < now)
1909 /* the last digit was too far in the past to be a sequence */
1910 if (param->dtmf == '*')
1911 /* only start is allowed in the sequence */
1917 /* we have a sequence of digits, see what we got */
1918 if (param->dtmf == '*')
1920 else if (param->dtmf>='0' && param->dtmf<='9')
1922 /* we need to have a star before we receive the digit of the sequence */
1923 if (e_dtmf_last == '*')
1924 e_dtmf_last = param->dtmf;
1925 } else if (param->dtmf == '#')
1928 if (e_dtmf_last>='0' && e_dtmf_last<='9')
1930 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf sequence *%c# detected.\n", ea_endpoint->ep_serial, e_dtmf_last);
1931 if (e_dtmf_last == '0')
1936 /* processing keypad function */
1938 keypad_function(e_dtmf_last);
1944 /* set last time of dtmf */
1949 /* check for ## hookflash during dialing */
1951 if (e_action->index==ACTION_PASSWORD
1952 || e_action->index==ACTION_PASSWORD_WRITE)
1954 if (param->dtmf=='#') /* current digit is '#' */
1956 if (e_state==EPOINT_STATE_IN_DISCONNECT
1957 || (e_state!=EPOINT_STATE_CONNECT && e_dtmf_time+3>=now && e_dtmf_last=='#')) /* when disconnected, just #. when dialing, ##. */
1974 /* dialing using dtmf digit */
1975 if (e_state==EPOINT_STATE_IN_OVERLAP)// && e_state==e_connectedmode)
1977 if (e_dialinginfo.id[0]=='\0' && !e_action)
1979 set_tone(portlist, "dialing");
1981 /* concat dialing string */
1982 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id))
1984 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1985 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1991 /* port MESSAGE_CRYPT */
1992 void EndpointAppPBX::port_crypt(struct port_list *portlist, int message_type, union parameter *param)
1994 /* send crypt response to cryptman */
1995 if (param->crypt.type == CR_MESSAGE_IND)
1996 cryptman_msg2man(param->crypt.data, param->crypt.len);
1998 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2001 /* port MESSAGE_OVERLAP */
2002 void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, union parameter *param)
2004 struct message *message;
2006 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2008 /* signal to call tool */
2009 admin_call_response(e_adminid, ADMIN_CALL_SETUP_ACK, "", 0, 0, 0);
2011 if (e_dialing_queue[0] && portlist)
2013 /* send what we have not dialed yet, because we had no setup complete */
2014 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing pending digits: '%s'\n", ea_endpoint->ep_serial, e_dialing_queue);
2015 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2016 SCPY(message->param.information.id, e_dialing_queue);
2017 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
2018 message_put(message);
2019 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
2020 e_dialing_queue[0] = '\0';
2022 /* check if pattern is available */
2023 if (!ea_endpoint->ep_portlist->next && portlist->early_b) /* one port_list relation and tones available */
2025 /* indicate patterns */
2026 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2027 message_put(message);
2029 /* connect audio, if not already */
2030 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2031 message->param.audiopath = CHANNEL_STATE_CONNECT;
2032 message_put(message);
2035 /* indicate no patterns */
2036 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
2037 message_put(message);
2039 /* disconnect audio, if not already */
2040 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2041 message->param.audiopath = CHANNEL_STATE_HOLD;
2042 message_put(message);
2044 new_state(EPOINT_STATE_OUT_OVERLAP);
2045 /* if we are in a join */
2046 if (ea_endpoint->ep_join_id)
2048 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2049 memcpy(&message->param, param, sizeof(union parameter));
2050 message_put(message);
2054 /* port MESSAGE_PROCEEDING */
2055 void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_type, union parameter *param)
2057 struct message *message;
2059 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2061 /* signal to call tool */
2062 admin_call_response(e_adminid, ADMIN_CALL_PROCEEDING, "", 0, 0, 0);
2064 e_state = EPOINT_STATE_OUT_PROCEEDING;
2065 /* check if pattern is availatle */
2066 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
2068 /* indicate patterns */
2069 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2070 message_put(message);
2072 /* connect audio, if not already */
2073 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2074 message->param.audiopath = CHANNEL_STATE_CONNECT;
2075 message_put(message);
2078 /* indicate no patterns */
2079 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
2080 message_put(message);
2082 /* disconnect audio, if not already */
2083 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2084 message->param.audiopath = CHANNEL_STATE_HOLD;
2085 message_put(message);
2087 /* if we are in a call */
2088 if (ea_endpoint->ep_join_id)
2090 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2091 memcpy(&message->param, param, sizeof(union parameter));
2092 message_put(message);
2096 /* port MESSAGE_ALERTING */
2097 void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type, union parameter *param)
2099 struct message *message;
2101 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2103 /* signal to call tool */
2104 admin_call_response(e_adminid, ADMIN_CALL_ALERTING, "", 0, 0, 0);
2106 new_state(EPOINT_STATE_OUT_ALERTING);
2107 /* check if pattern is available */
2108 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
2110 /* indicate patterns */
2111 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2112 message_put(message);
2114 /* connect audio, if not already */
2115 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2116 message->param.audiopath = CHANNEL_STATE_CONNECT;
2117 message_put(message);
2120 /* indicate no patterns */
2121 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
2122 message_put(message);
2124 /* disconnect audio, if not already */
2125 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2126 message->param.audiopath = CHANNEL_STATE_HOLD;
2127 message_put(message);
2129 /* if we are in a call */
2130 if (ea_endpoint->ep_join_id)
2132 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2133 memcpy(&message->param, param, sizeof(union parameter));
2134 message_put(message);
2138 /* port MESSAGE_CONNECT */
2139 void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, union parameter *param)
2141 struct message *message;
2143 unsigned long port_id = portlist->port_id;
2144 struct port_list *tportlist;
2146 struct interface *interface;
2148 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2150 /* signal to call tool */
2151 admin_call_response(e_adminid, ADMIN_CALL_CONNECT, numberrize_callerinfo(param->connectinfo.id,param->connectinfo.ntype), 0, 0, 0);
2153 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_connectinfo));
2154 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (start)\n", ea_endpoint->ep_serial);
2155 while(ea_endpoint->ep_portlist->next) /* as long as we have at least two ports */
2157 tportlist = ea_endpoint->ep_portlist;
2158 if (tportlist->port_id == port_id) /* if the first portlist is the calling one, the second must be a different one */
2159 tportlist = tportlist->next;
2160 if (tportlist->port_id == port_id)
2161 FATAL("EPOINT(%d) this should not happen since the portlist list must not have two links to the same port - exitting.\n");
2162 message = message_create(ea_endpoint->ep_serial, tportlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2163 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
2164 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2165 message_put(message);
2166 logmessage(message->type, &message->param, tportlist->port_id, DIRECTION_OUT);
2167 ea_endpoint->free_portlist(tportlist);
2169 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (end)\n", ea_endpoint->ep_serial);
2173 /* screen incoming connected id */
2174 interface = interface_first;
2177 if (!strcmp(e_connectinfo.interface, interface->name))
2181 interface = interface->next;
2184 screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface);
2186 /* screen connected name */
2188 SCPY(e_connectinfo.name, e_ext.name);
2190 /* add internal id to colp */
2191 SCPY(e_connectinfo.extension, e_ext.number);
2193 /* we store the connected port number */
2194 SCPY(e_extension_interface, e_connectinfo.interface);
2196 /* for internal and am calls, we get the extension's id */
2197 if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE)
2199 SCPY(e_connectinfo.id, e_ext.callerid);
2200 SCPY(e_connectinfo.extension, e_ext.number);
2201 e_connectinfo.itype = INFO_ITYPE_ISDN_EXTENSION;
2202 e_connectinfo.ntype = e_ext.callerid_type;
2203 e_connectinfo.present = e_ext.callerid_present;
2205 if (portlist->port_type==PORT_TYPE_VBOX_OUT)
2207 e_connectinfo.itype = INFO_ITYPE_VBOX;
2208 e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2211 new_state(EPOINT_STATE_CONNECT);
2213 /* set volume of rx and tx */
2214 if (e_ext.txvol!=256 || e_ext.rxvol!=256)
2216 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2217 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2218 message->param.mISDNsignal.rxvol = e_ext.txvol;
2219 message->param.mISDNsignal.txvol = e_ext.rxvol;
2220 message_put(message);
2223 e_cfnr_call = e_cfnr_release = 0;
2224 if (e_ext.number[0])
2225 e_dtmf = 1; /* allow dtmf */
2228 /* other calls with no caller id (or not available for the extension) and force colp */
2229 if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE)
2231 e_connectinfo.present = INFO_PRESENT_NOTAVAIL;
2232 if (portlist->port_type==PORT_TYPE_DSS1_TE_OUT || portlist->port_type==PORT_TYPE_DSS1_NT_OUT) /* external extension answered */
2234 port = find_port_id(portlist->port_id);
2237 SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.id, &e_connectinfo.ntype));
2238 e_connectinfo.present = INFO_PRESENT_ALLOWED;
2243 /* send connect to join */
2244 if (ea_endpoint->ep_join_id)
2246 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2247 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
2248 message_put(message);
2250 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2251 message->param.audiopath = CHANNEL_STATE_CONNECT;
2252 message_put(message);
2253 } else if (!e_adminid)
2256 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have a callback, so we create a call with cbcaller: \"%s\".\n", ea_endpoint->ep_serial, e_cbcaller);
2257 SCPY(e_ext.number, e_cbcaller);
2258 new_state(EPOINT_STATE_IN_OVERLAP);
2259 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) callback from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2261 /* get extension's info about terminal */
2262 if (!read_extension(&e_ext, e_ext.number))
2264 /* extension doesn't exist */
2265 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2266 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
2267 new_state(EPOINT_STATE_OUT_DISCONNECT);
2268 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
2272 /* put prefix in front of e_cbdialing */
2273 SPRINT(buffer, "%s%s", e_ext.prefix, e_cbdialing);
2274 SCPY(e_dialinginfo.id, buffer);
2275 e_dialinginfo.itype = INFO_ITYPE_ISDN;
2276 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
2278 /* use caller id (or if exist: id_next_call) for this call */
2279 e_callerinfo.screen = INFO_SCREEN_NETWORK;
2280 SCPY(e_callerinfo.extension, e_ext.number);
2281 if (e_ext.id_next_call_present >= 0)
2283 SCPY(e_callerinfo.id, e_ext.id_next_call);
2284 e_callerinfo.present = e_ext.id_next_call_present;
2285 e_callerinfo.ntype = e_ext.id_next_call_type;
2286 e_ext.id_next_call_present = -1;
2287 /* extension is written */
2288 write_extension(&e_ext, e_ext.number);
2291 SCPY(e_callerinfo.id, e_ext.callerid);
2292 e_callerinfo.present = e_ext.callerid_present;
2293 e_callerinfo.ntype = e_ext.callerid_type;
2296 e_connectedmode = 1; /* dtmf-hangup & disconnect prevention */
2299 /* check if caller id is NOT authenticated */
2300 if (!parse_callbackauth(e_ext.number, &e_callbackinfo))
2302 /* make call state to enter password */
2303 new_state(EPOINT_STATE_IN_OVERLAP);
2304 e_action = &action_password_write;
2305 e_match_timeout = 0;
2306 e_match_to_action = NULL;
2307 e_dialinginfo.id[0] = '\0';
2308 e_extdialing = strchr(e_dialinginfo.id, '\0');
2309 e_password_timeout = now+20;
2313 /* incoming call (callback) */
2314 e_ruleset = ruleset_main;
2316 e_rule = e_ruleset->rule_first;
2318 e_extdialing = e_dialinginfo.id;
2319 if (e_dialinginfo.id[0])
2321 set_tone(portlist, "dialing");
2325 set_tone(portlist, "dialpbx");
2328 } else /* testcall */
2330 set_tone(portlist, "hold");
2333 /* start recording if enabled, not when answering machine answers */
2334 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))
2336 /* check if we are a terminal */
2337 if (e_ext.number[0] == '\0')
2338 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
2341 port = find_port_id(portlist->port_id);
2343 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
2348 /* port MESSAGE_DISCONNECT MESSAGE_RELEASE */
2349 void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
2351 struct message *message;
2353 unsigned long port_id = portlist->port_id;
2357 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2359 /* signal to call tool */
2360 admin_call_response(e_adminid, (message_type==MESSAGE_DISCONNECT)?ADMIN_CALL_DISCONNECT:ADMIN_CALL_RELEASE, "", param->disconnectinfo.cause, param->disconnectinfo.location, 0);
2362 //#warning does this work? only disconnect when incoming port hat not already disconnected yet?
2363 if (e_state==EPOINT_STATE_IN_DISCONNECT && message_type!=MESSAGE_RELEASE)// || e_state==EPOINT_STATE_OUT_DISCONNECT || e_state==EPOINT_STATE_IDLE)
2365 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are already disconnected.\n", ea_endpoint->ep_serial);
2370 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);
2371 collect_cause(&e_multipoint_cause, &e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location);
2372 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new multipoint cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location);
2374 /* check if we have more than one portlist relation and we just ignore the disconnect */
2375 if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist->next)
2377 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the disconnect was from a multipoint call. we just release that relation.\n", ea_endpoint->ep_serial);
2378 portlist = ea_endpoint->ep_portlist;
2381 if (portlist->port_id == port_id)
2383 portlist = portlist->next;
2386 FATAL("EPOINT(%d) no portlist related to the calling port.\n", ea_endpoint->ep_serial);
2387 if (message_type != MESSAGE_RELEASE)
2389 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2390 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2391 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2392 message_put(message);
2393 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2395 ea_endpoint->free_portlist(portlist);
2396 return; /* one relation removed */
2398 if (e_state == EPOINT_STATE_CONNECT)
2400 /* use cause from port after connect */
2401 cause = param->disconnectinfo.cause;
2402 location = param->disconnectinfo.location;
2405 /* use multipoint cause if no connect yet */
2406 if (e_multipoint_cause)
2408 cause = e_multipoint_cause;
2409 location = e_multipoint_location;
2412 cause = CAUSE_NOUSER;
2413 location = LOCATION_PRIVATE_LOCAL;
2417 e_cfnr_call = e_cfnr_release = 0;
2419 /* process hangup */
2420 process_hangup(e_join_cause, e_join_location);
2421 e_multipoint_cause = 0;
2422 e_multipoint_location = 0;
2424 if (message_type == MESSAGE_DISCONNECT)
2426 /* tone to disconnected end */
2427 SPRINT(buffer, "cause_%02x", cause);
2428 if (ea_endpoint->ep_portlist)
2429 set_tone(ea_endpoint->ep_portlist, buffer);
2431 new_state(EPOINT_STATE_IN_DISCONNECT);
2434 if (ea_endpoint->ep_join_id)
2436 int haspatterns = 0;
2437 /* check if pattern is available */
2438 if (ea_endpoint->ep_portlist)
2439 if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->early_b)
2440 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
2441 && message_type != MESSAGE_RELEASE) // if we release, we are done
2445 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has patterns.\n", ea_endpoint->ep_serial);
2446 /* indicate patterns */
2447 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2448 message_put(message);
2449 /* connect audio, if not already */
2450 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2451 message->param.audiopath = CHANNEL_STATE_CONNECT;
2452 message_put(message);
2453 /* send disconnect */
2454 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2455 memcpy(&message->param, param, sizeof(union parameter));
2456 message_put(message);
2457 /* disable encryption if disconnected */
2458 //PERROR("REMOVE ME: state =%d, %d\n", e_crypt_state, e_crypt);
2460 cryptman_message(CI_DISCONNECT_IND, NULL, 0);
2464 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
2467 if (message_type == MESSAGE_RELEASE)
2468 ea_endpoint->free_portlist(portlist);
2469 release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, callcause, portcause */
2470 return; /* must exit here */
2473 /* port MESSAGE_TIMEOUT */
2474 void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type, union parameter *param)
2478 trace_header("TIMEOUT", DIRECTION_IN);
2479 message_type = MESSAGE_DISCONNECT;
2480 switch (param->state)
2482 case PORT_STATE_OUT_SETUP:
2483 case PORT_STATE_OUT_OVERLAP:
2484 add_trace("state", NULL, "outgoing setup/dialing");
2486 /* no user responding */
2487 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2488 return; /* must exit here */
2490 case PORT_STATE_IN_SETUP:
2491 case PORT_STATE_IN_OVERLAP:
2492 add_trace("state", NULL, "incoming setup/dialing");
2493 param->disconnectinfo.cause = CAUSE_INVALID; /* number incomplete */
2494 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2497 case PORT_STATE_OUT_PROCEEDING:
2498 add_trace("state", NULL, "outgoing proceeding");
2500 param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
2501 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2502 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2503 return; /* must exit here */
2505 case PORT_STATE_IN_PROCEEDING:
2506 add_trace("state", NULL, "incoming proceeding");
2507 param->disconnectinfo.cause = CAUSE_NOUSER;
2508 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL; /* no user responding */
2511 case PORT_STATE_OUT_ALERTING:
2512 add_trace("state", NULL, "outgoing alerting");
2514 param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
2515 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2516 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2517 return; /* must exit here */
2519 case PORT_STATE_CONNECT:
2520 add_trace("state", NULL, "connect");
2522 param->disconnectinfo.cause = CAUSE_NORMAL; /* normal */
2523 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2524 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2525 return; /* must exit here */
2527 case PORT_STATE_IN_ALERTING:
2528 add_trace("state", NULL, "incoming alerting");
2529 param->disconnectinfo.cause = CAUSE_NOANSWER;
2530 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2533 case PORT_STATE_IN_DISCONNECT:
2534 case PORT_STATE_OUT_DISCONNECT:
2535 add_trace("state", NULL, "disconnect");
2537 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
2538 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2539 return; /* must exit here */
2542 param->disconnectinfo.cause = 31; /* normal unspecified */
2543 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2546 /* release call, disconnect isdn */
2548 new_state(EPOINT_STATE_OUT_DISCONNECT);
2549 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2550 SCPY(e_tone, cause);
2553 set_tone(portlist, cause);
2554 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2555 portlist = portlist->next;
2557 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
2560 /* port MESSAGE_NOTIFY */
2561 void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, union parameter *param)
2563 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2565 struct message *message;
2569 /* signal to call tool */
2570 admin_call_response(e_adminid, ADMIN_CALL_NOTIFY, numberrize_callerinfo(param->notifyinfo.id,param->notifyinfo.ntype), 0, 0, param->notifyinfo.notify);
2571 if (param->notifyinfo.notify)
2573 e_rx_state = track_notify(e_rx_state, param->notifyinfo.notify);
2576 /* if we get notification from stack, local shows if we disabled/enabled audio stream */
2577 if (param->notifyinfo.local) switch(param->notifyinfo.notify)
2579 case INFO_NOTIFY_REMOTE_HOLD:
2580 case INFO_NOTIFY_USER_SUSPENDED:
2581 /* tell call about it */
2582 if (ea_endpoint->ep_join_id)
2584 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2585 message->param.audiopath = CHANNEL_STATE_HOLD;
2586 message_put(message);
2590 case INFO_NOTIFY_REMOTE_RETRIEVAL:
2591 case INFO_NOTIFY_USER_RESUMED:
2592 /* set volume of rx and tx */
2593 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
2594 if (e_ext.txvol!=256 || e_ext.rxvol!=256)
2597 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2598 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2599 message->param.mISDNsignal.rxvol = e_ext.txvol;
2600 message->param.mISDNsignal.txvol = e_ext.rxvol;
2601 message_put(message);
2603 /* set current tone */
2605 set_tone(portlist, e_tone);
2606 /* tell call about it */
2607 if (ea_endpoint->ep_join_id)
2609 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2610 message->param.audiopath = CHANNEL_STATE_CONNECT;
2611 message_put(message);
2616 /* get name of notify */
2617 switch(param->notifyinfo.notify)
2623 logtext = "USER_SUSPENDED";
2626 logtext = "BEARER_SERVICE_CHANGED";
2629 logtext = "USER_RESUMED";
2632 logtext = "CONFERENCE_ESTABLISHED";
2635 logtext = "CONFERENCE_DISCONNECTED";
2638 logtext = "OTHER_PARTY_ADDED";
2641 logtext = "ISOLATED";
2644 logtext = "REATTACHED";
2647 logtext = "OTHER_PARTY_ISOLATED";
2650 logtext = "OTHER_PARTY_REATTACHED";
2653 logtext = "OTHER_PARTY_SPLIT";
2656 logtext = "OTHER_PARTY_DISCONNECTED";
2659 logtext = "CONFERENCE_FLOATING";
2662 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
2665 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
2668 logtext = "CALL_IS_A_WAITING_CALL";
2671 logtext = "DIVERSION_ACTIVATED";
2674 logtext = "RESERVED_CT_1";
2677 logtext = "RESERVED_CT_2";
2680 logtext = "REVERSE_CHARGING";
2683 logtext = "REMOTE_HOLD";
2686 logtext = "REMOTE_RETRIEVAL";
2689 logtext = "CALL_IS_DIVERTING";
2692 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
2697 /* notify call if available */
2698 if (ea_endpoint->ep_join_id)
2700 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOTIFY);
2701 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
2702 message_put(message);
2707 /* port MESSAGE_FACILITY */
2708 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
2710 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2712 struct message *message;
2714 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_FACILITY);
2715 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2716 message_put(message);
2719 /* port MESSAGE_SUSPEND */
2720 /* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
2721 void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
2723 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2725 /* epoint is now parked */
2726 ea_endpoint->ep_park = 1;
2727 memcpy(ea_endpoint->ep_park_callid, param->parkinfo.callid, sizeof(ea_endpoint->ep_park_callid));
2728 ea_endpoint->ep_park_len = (param->parkinfo.len>8)?8:param->parkinfo.len;
2730 /* remove port relation */
2731 ea_endpoint->free_portlist(portlist);
2734 /* port MESSAGE_RESUME */
2735 /* NOTE: before resume, the active-notification must be done in order to set call mixer */
2736 void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
2738 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2740 /* epoint is now resumed */
2741 ea_endpoint->ep_park = 0;
2746 /* port sends message to the endpoint
2748 void EndpointAppPBX::ea_message_port(unsigned long port_id, int message_type, union parameter *param)
2750 struct port_list *portlist;
2751 struct message *message;
2753 portlist = ea_endpoint->ep_portlist;
2756 if (port_id == portlist->port_id)
2758 portlist = portlist->next;
2762 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);
2766 // PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
2767 switch(message_type)
2769 case MESSAGE_DATA: /* data from port */
2770 /* check if there is a call */
2771 if (!ea_endpoint->ep_join_id)
2773 /* continue if only one portlist */
2774 if (ea_endpoint->ep_portlist->next != NULL)
2776 /* forward message */
2777 message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2780 case MESSAGE_TONE_EOF: /* tone is end of file */
2781 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
2784 if (e_action->index == ACTION_VBOX_PLAY)
2788 if (e_action->index == ACTION_EFI)
2795 case MESSAGE_TONE_COUNTER: /* counter info received */
2796 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);
2798 if (e_action->index == ACTION_VBOX_PLAY)
2800 e_vbox_counter = param->counter.current;
2801 if (param->counter.max >= 0)
2802 e_vbox_counter_max = param->counter.max;
2806 /* PORT sends SETUP message */
2808 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);
2809 if (e_state!=EPOINT_STATE_IDLE)
2811 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
2814 port_setup(portlist, message_type, param);
2817 /* PORT sends INFORMATION message */
2818 case MESSAGE_INFORMATION: /* additional digits received */
2819 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);
2820 port_information(portlist, message_type, param);
2823 /* PORT sends FACILITY message */
2824 case MESSAGE_FACILITY:
2825 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2826 port_facility(portlist, message_type, param);
2829 /* PORT sends DTMF message */
2830 case MESSAGE_DTMF: /* dtmf digits received */
2831 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);
2832 port_dtmf(portlist, message_type, param);
2835 /* PORT sends CRYPT message */
2836 case MESSAGE_CRYPT: /* crypt response received */
2837 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) crypt response=%d\n", ea_endpoint->ep_serial, param->crypt.type);
2838 port_crypt(portlist, message_type, param);
2841 /* PORT sends MORE message */
2842 case MESSAGE_OVERLAP:
2843 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);
2844 if (e_state != EPOINT_STATE_OUT_SETUP)
2846 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);
2849 port_overlap(portlist, message_type, param);
2852 /* PORT sends PROCEEDING message */
2853 case MESSAGE_PROCEEDING: /* port is proceeding */
2854 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);
2855 if (e_state!=EPOINT_STATE_OUT_SETUP
2856 && e_state!=EPOINT_STATE_OUT_OVERLAP)
2858 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);
2861 port_proceeding(portlist, message_type, param);
2864 /* PORT sends ALERTING message */
2865 case MESSAGE_ALERTING:
2866 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);
2867 if (e_state!=EPOINT_STATE_OUT_SETUP
2868 && e_state!=EPOINT_STATE_OUT_OVERLAP
2869 && e_state!=EPOINT_STATE_OUT_PROCEEDING)
2871 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);
2874 port_alerting(portlist, message_type, param);
2877 /* PORT sends CONNECT message */
2878 case MESSAGE_CONNECT:
2879 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);
2880 if (e_state!=EPOINT_STATE_OUT_SETUP
2881 && e_state!=EPOINT_STATE_OUT_OVERLAP
2882 && e_state!=EPOINT_STATE_OUT_PROCEEDING
2883 && e_state!=EPOINT_STATE_OUT_ALERTING)
2885 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
2888 port_connect(portlist, message_type, param);
2891 /* PORT sends DISCONNECT message */
2892 case MESSAGE_DISCONNECT: /* port is disconnected */
2893 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);
2894 port_disconnect_release(portlist, message_type, param);
2897 /* PORT sends a RELEASE message */
2898 case MESSAGE_RELEASE: /* port releases */
2899 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);
2900 /* portlist is release at port_disconnect_release, thanx Paul */
2901 port_disconnect_release(portlist, message_type, param);
2904 /* PORT sends a TIMEOUT message */
2905 case MESSAGE_TIMEOUT:
2906 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);
2907 port_timeout(portlist, message_type, param);
2908 break; /* release */
2910 /* PORT sends a NOTIFY message */
2911 case MESSAGE_NOTIFY:
2912 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);
2913 port_notify(portlist, message_type, param);
2916 /* PORT sends a SUSPEND message */
2917 case MESSAGE_SUSPEND:
2918 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);
2919 port_suspend(portlist, message_type, param);
2920 break; /* suspend */
2922 /* PORT sends a RESUME message */
2923 case MESSAGE_RESUME:
2924 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);
2925 port_resume(portlist, message_type, param);
2929 /* port assigns bchannel */
2930 case MESSAGE_BCHANNEL: /* bchannel assignment messafe */
2931 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);
2932 /* only one port is expected to be connected to bchannel */
2933 message = message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2934 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_IN);
2940 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);
2943 /* Note: this endpoint may be destroyed, so we MUST return */
2947 /* messages from join
2949 /* join MESSAGE_CRYPT */
2950 void EndpointAppPBX::join_crypt(struct port_list *portlist, int message_type, union parameter *param)
2952 switch(param->crypt.type)
2954 /* message from remote port to "crypt manager" */
2955 case CU_ACTK_REQ: /* activate key-exchange */
2956 case CU_ACTS_REQ: /* activate shared key */
2957 case CU_DACT_REQ: /* deactivate */
2958 case CU_INFO_REQ: /* request last info message */
2959 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2962 /* message from "crypt manager" to user */
2963 case CU_ACTK_CONF: /* key-echange done */
2964 case CU_ACTS_CONF: /* shared key done */
2965 case CU_DACT_CONF: /* deactivated */
2966 case CU_DACT_IND: /* deactivated */
2967 case CU_ERROR_IND: /* receive error message */
2968 case CU_INFO_IND: /* receive info message */
2969 case CU_INFO_CONF: /* receive info message */
2970 encrypt_result(param->crypt.type, (char *)param->crypt.data);
2974 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);
2978 /* join MESSAGE_INFORMATION */
2979 void EndpointAppPBX::join_information(struct port_list *portlist, int message_type, union parameter *param)
2981 struct message *message;
2987 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2988 memcpy(&message->param.information, ¶m->information, sizeof(struct dialing_info));
2989 message_put(message);
2990 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2991 portlist = portlist->next;
2995 /* join MESSAGE_FACILITY */
2996 void EndpointAppPBX::join_facility(struct port_list *portlist, int message_type, union parameter *param)
2998 struct message *message;
3000 if (!e_ext.facility)
3007 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_FACILITY);
3008 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
3009 message_put(message);
3010 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3011 portlist = portlist->next;
3015 /* join MESSAGE_MORE */
3016 void EndpointAppPBX::join_overlap(struct port_list *portlist, int message_type, union parameter *param)
3018 struct message *message;
3020 new_state(EPOINT_STATE_IN_OVERLAP);
3023 if (e_join_pattern && e_ext.own_setup)
3025 /* disconnect audio */
3026 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3027 message->param.audiopath = CHANNEL_STATE_HOLD;
3028 message_put(message);
3030 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
3032 set_tone(portlist, "dialtone");
3035 if (e_ext.number[0])
3036 set_tone(portlist, "dialpbx");
3038 set_tone(portlist, "dialtone");
3041 /* join MESSAGE_PROCEEDING */
3042 void EndpointAppPBX::join_proceeding(struct port_list *portlist, int message_type, union parameter *param)
3044 struct message *message;
3046 new_state(EPOINT_STATE_IN_PROCEEDING);
3048 /* own proceeding tone */
3051 /* connect / disconnect audio */
3052 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3053 if (e_ext.own_proceeding)
3054 message->param.audiopath = CHANNEL_STATE_HOLD;
3056 message->param.audiopath = CHANNEL_STATE_CONNECT;
3057 message_put(message);
3059 // UCPY(e_join_tone, "proceeding");
3062 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3063 message_put(message);
3064 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3066 set_tone(portlist, "proceeding");
3069 /* join MESSAGE_ALERTING */
3070 void EndpointAppPBX::join_alerting(struct port_list *portlist, int message_type, union parameter *param)
3072 struct message *message;
3074 new_state(EPOINT_STATE_IN_ALERTING);
3076 /* own alerting tone */
3079 /* connect / disconnect audio */
3080 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3081 if (e_ext.own_alerting)
3082 message->param.audiopath = CHANNEL_STATE_HOLD;
3084 message->param.audiopath = CHANNEL_STATE_CONNECT;
3085 message_put(message);
3089 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
3090 message_put(message);
3091 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3093 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
3095 set_tone(portlist, "ringing");
3098 if (e_ext.number[0])
3099 set_tone(portlist, "ringpbx");
3101 set_tone(portlist, "ringing");
3104 /* join MESSAGE_CONNECT */
3105 void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type, union parameter *param)
3107 struct message *message;
3108 struct interface *interface;
3110 new_state(EPOINT_STATE_CONNECT);
3111 // UCPY(e_join_tone, "");
3112 if (e_ext.number[0])
3113 e_dtmf = 1; /* allow dtmf */
3115 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_callerinfo));
3118 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3119 memcpy(&message->param, param, sizeof(union parameter));
3120 /* screen incoming caller id */
3121 interface = interface_first;
3124 if (!strcmp(e_connectinfo.interface, interface->name))
3128 interface = interface->next;
3131 screen(1, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface);
3132 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(e_connectinfo));
3134 /* screen clip if prefix is required */
3135 if (e_ext.number[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0])
3137 SCPY(message->param.connectinfo.id, e_ext.clip_prefix);
3138 SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype));
3139 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
3142 /* use internal caller id */
3143 if (e_ext.number[0] && e_connectinfo.extension[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
3145 SCPY(message->param.connectinfo.id, e_connectinfo.extension);
3146 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
3149 /* handle restricted caller ids */
3150 apply_callerid_restriction(e_ext.anon_ignore, message->param.connectinfo.id, &message->param.connectinfo.ntype, &message->param.connectinfo.present, &message->param.connectinfo.screen, message->param.connectinfo.extension, message->param.connectinfo.name);
3151 /* display callerid if desired for extension */
3152 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));
3154 /* use conp, if enabld */
3156 message->param.connectinfo.name[0] = '\0';
3159 message_put(message);
3160 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3162 set_tone(portlist, NULL);
3164 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3165 message->param.audiopath = CHANNEL_STATE_CONNECT;
3166 message_put(message);
3170 /* join MESSAGE_DISCONNECT MESSAGE_RELEASE */
3171 void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *param)
3174 struct message *message;
3175 struct port_list *portlist = NULL;
3178 /* be sure that we are active */
3180 e_tx_state = NOTIFY_STATE_ACTIVE;
3182 /* we are powerdialing, if e_powerdialing is set and limit is not exceeded if given */
3183 if (e_powerdialing && ((e_powercount+1)<e_powerlimit || e_powerlimit<1))
3185 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
3187 /* set time for power dialing */
3188 e_powerdialing = now_d + e_powerdelay; /* set redial in the future */
3191 /* set redial tone */
3192 if (ea_endpoint->ep_portlist)
3196 set_tone(ea_endpoint->ep_portlist, "redial");
3197 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);
3198 /* send proceeding when powerdialing and still setup (avoid dialing timeout) */
3199 if (e_state==EPOINT_STATE_IN_OVERLAP)
3201 new_state(EPOINT_STATE_IN_PROCEEDING);
3202 if (ea_endpoint->ep_portlist)
3204 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3205 message_put(message);
3206 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3208 /* caused the error, that the first knock sound was not there */
3209 /* set_tone(portlist, "proceeding"); */
3211 /* send display of powerdialing */
3212 if (e_ext.display_dialing)
3214 portlist = ea_endpoint->ep_portlist;
3217 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3219 SPRINT(message->param.notifyinfo.display, "Retry %d of %d", e_powercount, e_powerlimit);
3221 SPRINT(message->param.notifyinfo.display, "Retry %d", e_powercount);
3222 message_put(message);
3223 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3224 portlist = portlist->next;
3233 if ((e_state!=EPOINT_STATE_CONNECT
3234 && e_state!=EPOINT_STATE_OUT_DISCONNECT
3235 && e_state!=EPOINT_STATE_IN_OVERLAP
3236 && e_state!=EPOINT_STATE_IN_PROCEEDING
3237 && e_state!=EPOINT_STATE_IN_ALERTING)
3238 || !ea_endpoint->ep_portlist) /* or no port */
3240 process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
3241 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause); /* RELEASE_TYPE, join, port */
3242 return; /* must exit here */
3247 e_join_cause = param->disconnectinfo.cause;
3248 e_join_location = param->disconnectinfo.location;
3251 /* on release we need the audio again! */
3252 if (message_type == MESSAGE_RELEASE)
3255 ea_endpoint->ep_join_id = 0;
3257 /* disconnect and select tone */
3258 new_state(EPOINT_STATE_OUT_DISCONNECT);
3259 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
3260 /* if own_cause, we must release the join */
3261 if (e_ext.own_cause /* own cause */
3262 || !e_join_pattern) /* no patterns */
3264 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);
3265 if (message_type != MESSAGE_RELEASE)
3266 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
3268 } else /* else we enable audio */
3270 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3271 message->param.audiopath = CHANNEL_STATE_CONNECT;
3272 message_put(message);
3274 /* send disconnect message */
3275 SCPY(e_tone, cause);
3276 portlist = ea_endpoint->ep_portlist;
3279 set_tone(portlist, cause);
3280 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
3281 portlist = portlist->next;
3285 /* join MESSAGE_SETUP */
3286 void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, union parameter *param)
3288 struct message *message;
3289 struct interface *interface;
3291 /* if we already in setup state, we just update the dialing with new digits */
3292 if (e_state == EPOINT_STATE_OUT_SETUP
3293 || e_state == EPOINT_STATE_OUT_OVERLAP)
3295 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we are in setup state, so we do overlap dialing.\n", ea_endpoint->ep_serial);
3296 /* if digits changed, what we have already dialed */
3297 if (!!strncmp(e_dialinginfo.id,param->setup.dialinginfo.id,strlen(e_dialinginfo.id)))
3299 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);
3300 /* release all ports */
3301 while((portlist = ea_endpoint->ep_portlist))
3303 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
3304 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
3305 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3306 message_put(message);
3307 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3308 ea_endpoint->free_portlist(portlist);
3311 /* disconnect audio */
3312 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3313 message->param.audiopath = CHANNEL_STATE_HOLD;
3314 message_put(message);
3316 /* get dialing info */
3317 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3318 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3319 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3320 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3321 new_state(EPOINT_STATE_OUT_OVERLAP);
3324 e_redial = now_d + 1; /* set redial one second in the future */
3327 /* if we have a pending redial, so we just adjust the dialing number */
3330 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);
3331 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3334 if (!ea_endpoint->ep_portlist)
3336 PERROR("ERROR: overlap dialing to a NULL port relation\n");
3338 if (ea_endpoint->ep_portlist->next)
3340 PERROR("ERROR: overlap dialing to a port_list port relation\n");
3342 if (e_state == EPOINT_STATE_OUT_SETUP)
3345 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);
3346 SCAT(e_dialing_queue, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3350 /* get what we have not dialed yet */
3351 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));
3352 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
3353 SCPY(message->param.information.id, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3354 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
3355 message_put(message);
3356 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3358 /* always store what we have dialed or queued */
3359 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3363 if (e_state != EPOINT_STATE_IDLE)
3365 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
3368 /* if an internal extension is dialed, copy that number */
3369 if (param->setup.dialinginfo.itype==INFO_ITYPE_ISDN_EXTENSION || param->setup.dialinginfo.itype==INFO_ITYPE_VBOX)
3370 SCPY(e_ext.number, param->setup.dialinginfo.id);
3371 /* if an internal extension is dialed, get extension's info about caller */
3372 if (e_ext.number[0])
3374 if (!read_extension(&e_ext, e_ext.number))
3376 e_ext.number[0] = '\0';
3377 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the called terminal='%s' is not found in directory tree!\n", ea_endpoint->ep_serial, e_ext.number);
3381 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3382 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3383 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3384 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3386 /* screen incoming caller id */
3387 interface = interface_first;
3390 if (!strcmp(e_callerinfo.interface, interface->name))
3394 interface = interface->next;
3397 screen(1, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface);
3399 /* process (voice over) data calls */
3400 if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO)
3402 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) handling data call as audio call: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
3403 memset(&e_capainfo, 0, sizeof(e_capainfo));
3404 e_capainfo.bearer_capa = INFO_BC_AUDIO;
3405 e_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
3406 e_capainfo.bearer_info1 = (options.law=='u')?INFO_INFO1_ULAW:INFO_INFO1_ALAW;
3409 new_state(EPOINT_STATE_OUT_SETUP);
3410 /* call special setup routine */
3414 /* join MESSAGE_mISDNSIGNAL */
3415 void EndpointAppPBX::join_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param)
3417 struct message *message;
3421 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
3422 memcpy(&message->param, param, sizeof(union parameter));
3423 message_put(message);
3424 portlist = portlist->next;
3428 /* join MESSAGE_NOTIFY */
3429 void EndpointAppPBX::join_notify(struct port_list *portlist, int message_type, union parameter *param)
3431 struct message *message;
3434 if (param->notifyinfo.notify)
3436 new_state = track_notify(e_tx_state, param->notifyinfo.notify);
3437 // /* if notification was generated locally, we turn hold music on/off */
3438 // if (param->notifyinfo.local)
3439 // 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)
3444 if (new_state!=NOTIFY_STATE_HOLD && new_state!=NOTIFY_STATE_SUSPEND)
3446 if (!strcmp(e_tone, "hold")) // don't interrupt other tones
3450 set_tone(portlist, "");
3451 portlist = portlist->next;
3454 portlist = ea_endpoint->ep_portlist;
3459 if (new_state==NOTIFY_STATE_HOLD || new_state==NOTIFY_STATE_SUSPEND)
3463 set_tone(portlist, "hold");
3464 portlist = portlist->next;
3466 portlist = ea_endpoint->ep_portlist;
3471 /* save new state */
3472 e_tx_state = new_state;
3475 /* notify port(s) about it */
3478 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3479 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
3480 /* handle restricted caller ids */
3481 apply_callerid_restriction(e_ext.anon_ignore, message->param.notifyinfo.id, &message->param.notifyinfo.ntype, &message->param.notifyinfo.present, 0, message->param.notifyinfo.extension, NULL);
3482 /* display callerid if desired for extension */
3483 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));
3484 message_put(message);
3485 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3486 portlist = portlist->next;
3490 /* JOIN sends messages to the endpoint
3492 void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, union parameter *param)
3494 struct port_list *portlist;
3495 struct message *message;
3499 PERROR("EPOINT(%d) error: JOIN == NULL.\n", ea_endpoint->ep_serial);
3503 portlist = ea_endpoint->ep_portlist;
3505 /* send MESSAGE_DATA to port */
3506 if (message_type == MESSAGE_DATA)
3508 if (join_id == ea_endpoint->ep_join_id) // still linked with JOIN
3510 /* skip if no port relation */
3513 /* skip if more than one port relation */
3516 /* forward audio data to port */
3517 message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3522 // 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);
3523 switch(message_type)
3525 /* JOIN SENDS TONE message */
3527 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);
3528 set_tone(portlist, param->tone.name);
3531 /* JOIN SENDS CRYPT message */
3533 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);
3534 join_crypt(portlist, message_type, param);
3537 /* JOIN sends INFORMATION message */
3538 case MESSAGE_INFORMATION:
3539 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);
3540 join_information(portlist, message_type, param);
3543 /* JOIN sends FACILITY message */
3544 case MESSAGE_FACILITY:
3545 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);
3546 join_facility(portlist, message_type, param);
3549 /* JOIN sends OVERLAP message */
3550 case MESSAGE_OVERLAP:
3551 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);
3552 if (e_state!=EPOINT_STATE_IN_SETUP
3553 && e_state!=EPOINT_STATE_IN_OVERLAP)
3555 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3558 join_overlap(portlist, message_type, param);
3561 /* JOIN sends PROCEEDING message */
3562 case MESSAGE_PROCEEDING:
3563 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);
3564 if(e_state!=EPOINT_STATE_IN_OVERLAP)
3566 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3569 join_proceeding(portlist, message_type, param);
3572 /* JOIN sends ALERTING message */
3573 case MESSAGE_ALERTING:
3574 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);
3575 if (e_state!=EPOINT_STATE_IN_OVERLAP
3576 && e_state!=EPOINT_STATE_IN_PROCEEDING)
3578 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state.\n", ea_endpoint->ep_serial);
3581 join_alerting(portlist, message_type, param);
3584 /* JOIN sends CONNECT message */
3585 case MESSAGE_CONNECT:
3586 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);
3587 if (e_state!=EPOINT_STATE_IN_OVERLAP
3588 && e_state!=EPOINT_STATE_IN_PROCEEDING
3589 && e_state!=EPOINT_STATE_IN_ALERTING)
3591 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
3594 join_connect(portlist, message_type, param);
3597 /* JOIN sends DISCONNECT/RELEASE message */
3598 case MESSAGE_DISCONNECT: /* JOIN disconnect */
3599 case MESSAGE_RELEASE: /* JOIN releases */
3600 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);
3601 join_disconnect_release(message_type, param);
3604 /* JOIN sends SETUP message */
3606 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);
3607 join_setup(portlist, message_type, param);
3610 /* JOIN sends special mISDNSIGNAL message */
3611 case MESSAGE_mISDNSIGNAL: /* isdn message to port */
3612 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);
3613 join_mISDNsignal(portlist, message_type, param);
3617 /* JOIN requests bchannel */
3618 case MESSAGE_BCHANNEL: /* indicates the need of own bchannel access */
3619 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);
3620 /* only one port is expected to be connected to bchannel */
3627 set_tone(portlist, NULL);
3628 message = message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3629 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3633 /* JOIN has pattern available */
3634 case MESSAGE_PATTERN: /* indicating pattern available */
3635 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);
3636 if (!e_join_pattern)
3638 PDEBUG(DEBUG_EPOINT, "-> pattern becomes available\n");
3643 set_tone(portlist, NULL);
3644 portlist = portlist->next;
3646 /* connect our audio tx and rx (blueboxing should be possibe before connect :)*/
3647 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3648 message->param.audiopath = CHANNEL_STATE_CONNECT;
3649 message_put(message);
3650 // /* tell remote epoint to connect audio also, because we like to hear the patterns */
3651 // message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_REMOTE_AUDIO);
3652 // message->param.audiopath = CHANNEL_STATE_CONNECT;
3653 // message_put(message);
3654 // patterns are available, remote already connected audio
3658 /* JOIN has no pattern available */
3659 case MESSAGE_NOPATTERN: /* indicating no pattern available */
3660 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);
3663 PDEBUG(DEBUG_EPOINT, "-> pattern becomes unavailable\n");
3665 /* disconnect our audio tx and rx */
3666 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3667 message->param.audiopath = CHANNEL_STATE_HOLD;
3668 message_put(message);
3673 /* JOIN (dunno at the moment) */
3674 case MESSAGE_REMOTE_AUDIO:
3675 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);
3676 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3677 message->param.audiopath = param->channel;
3678 message_put(message);
3682 /* JOIN sends a notify message */
3683 case MESSAGE_NOTIFY:
3684 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);
3685 join_notify(portlist, message_type, param);
3689 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);
3694 /* pick_join will connect the first incoming call found. the endpoint
3695 * will receivce a MESSAGE_CONNECT.
3697 int match_list(char *list, char *item)
3699 char *end, *next = NULL;
3701 /* no list make matching */
3707 /* eliminate white spaces */
3708 while (*list <= ' ')
3715 /* if end of list is reached, we return */
3716 if (list[0] == '\0')
3718 /* if we have more than one entry (left) */
3719 if ((end = strchr(list, ',')))
3722 next = end = strchr(list, '\0');
3723 while (*(end-1) <= ' ')
3725 /* if string part matches item */
3726 if (!strncmp(list, item, end-list))
3732 void EndpointAppPBX::pick_join(char *extensions)
3734 struct message *message;
3735 struct port_list *portlist;
3737 class EndpointAppPBX *eapp, *found;
3739 class JoinPBX *joinpbx;
3740 struct join_relation *relation;
3743 /* find an endpoint that is ringing internally or vbox with higher priority */
3746 eapp = apppbx_first;
3749 if (eapp!=this && ea_endpoint->ep_portlist)
3751 portlist = eapp->ea_endpoint->ep_portlist;
3754 if ((port = find_port_id(portlist->port_id)))
3756 if (port->p_type == PORT_TYPE_VBOX_OUT)
3758 if (match_list(extensions, eapp->e_ext.number))
3765 if ((port->p_type==PORT_TYPE_DSS1_NT_OUT || port->p_type==PORT_TYPE_DSS1_TE_OUT)
3766 && port->p_state==PORT_STATE_OUT_ALERTING)
3767 if (match_list(extensions, eapp->e_ext.number))
3772 portlist = portlist->next;
3780 /* if no endpoint found */
3783 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);
3785 set_tone(ea_endpoint->ep_portlist, "cause_10");
3786 message_disconnect_port(ea_endpoint->ep_portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
3787 new_state(EPOINT_STATE_OUT_DISCONNECT);
3792 if (ea_endpoint->ep_join_id)
3794 PERROR("EPOINT(%d) we already have a join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3797 if (!eapp->ea_endpoint->ep_join_id)
3799 PERROR("EPOINT(%d) ringing endpoint has no join.\n", ea_endpoint->ep_serial);
3802 join = find_join_id(eapp->ea_endpoint->ep_join_id);
3805 PERROR("EPOINT(%d) ringing endpoint's join not found.\n", ea_endpoint->ep_serial);
3808 if (join->j_type != JOIN_TYPE_PBX)
3810 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ringing endpoint's join is not a PBX join, so we must reject.\n", ea_endpoint->ep_serial);
3813 joinpbx = (class JoinPBX *)join;
3814 relation = joinpbx->j_relation;
3817 PERROR("EPOINT(%d) ringing endpoint's join has no relation. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3820 while (relation->epoint_id != eapp->ea_endpoint->ep_serial)
3822 relation = relation->next;
3825 PERROR("EPOINT(%d) ringing endpoint's join has no relation to that join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3830 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found ringing endpoint: %d.\n", ea_endpoint->ep_serial, eapp->ea_endpoint->ep_serial);
3832 if (options.deb & DEBUG_EPOINT)
3834 class Join *debug_c = join_first;
3835 class Endpoint *debug_e = epoint_first;
3836 class Port *debug_p = port_first;
3838 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(before)");
3840 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3843 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3844 debug_c = debug_c->next;
3846 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3849 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3850 debug_e = debug_e->next;
3852 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3855 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld (active)\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3856 debug_p = debug_p->next;
3861 ea_endpoint->ep_join_id = eapp->ea_endpoint->ep_join_id; /* we get the join */
3862 relation->epoint_id = ea_endpoint->ep_serial; /* the join gets us */
3863 eapp->ea_endpoint->ep_join_id = 0; /* the ringing endpoint will get disconnected */
3865 /* connnecting our endpoint */
3866 new_state(EPOINT_STATE_CONNECT);
3868 set_tone(ea_endpoint->ep_portlist, NULL);
3870 /* now we send a release to the ringing endpoint */
3871 message = message_create(ea_endpoint->ep_join_id, eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3872 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
3873 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3874 message_put(message);
3876 /* we send a connect to the join with our caller id */
3877 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CONNECT);
3878 SCPY(message->param.connectinfo.id, e_callerinfo.id);
3879 message->param.connectinfo.present = e_callerinfo.present;
3880 message->param.connectinfo.screen = e_callerinfo.screen;
3881 message->param.connectinfo.itype = e_callerinfo.itype;
3882 message->param.connectinfo.ntype = e_callerinfo.ntype;
3883 message_put(message);
3885 /* we send a connect to our port with the remote callerid */
3886 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3887 SCPY(message->param.connectinfo.id, eapp->e_callerinfo.id);
3888 message->param.connectinfo.present = eapp->e_callerinfo.present;
3889 message->param.connectinfo.screen = eapp->e_callerinfo.screen;
3890 message->param.connectinfo.itype = eapp->e_callerinfo.itype;
3891 message->param.connectinfo.ntype = eapp->e_callerinfo.ntype;
3892 /* handle restricted caller ids */
3893 apply_callerid_restriction(e_ext.anon_ignore, message->param.connectinfo.id, &message->param.connectinfo.ntype, &message->param.connectinfo.present, &message->param.connectinfo.screen, message->param.connectinfo.extension, message->param.connectinfo.name);
3894 /* display callerid if desired for extension */
3895 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));
3896 message_put(message);
3898 /* we send a connect to the audio path (not for vbox) */
3899 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3900 message->param.audiopath = CHANNEL_STATE_CONNECT;
3901 message_put(message);
3903 /* beeing paranoid, we make call update */
3904 joinpbx->j_updatebridge = 1;
3906 if (options.deb & DEBUG_EPOINT)
3908 class Join *debug_c = join_first;
3909 class Endpoint *debug_e = epoint_first;
3910 class Port *debug_p = port_first;
3912 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(after)");
3914 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3917 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3918 debug_c = debug_c->next;
3920 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3923 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3924 debug_e = debug_e->next;
3926 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3929 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3930 debug_p = debug_p->next;
3936 /* join calls (look for a join that is on hold (same isdn interface/terminal))
3938 void EndpointAppPBX::join_join(void)
3940 struct message *message;
3941 struct join_relation *our_relation, *other_relation;
3942 struct join_relation **our_relation_pointer, **other_relation_pointer;
3943 class Join *our_join, *other_join;
3944 class JoinPBX *our_joinpbx, *other_joinpbx;
3945 class EndpointAppPBX *other_eapp; class Endpoint *temp_epoint;
3946 class Port *our_port, *other_port;
3947 class Pdss1 *our_pdss1, *other_pdss1;
3949 /* are we a candidate to join a join */
3950 our_join = find_join_id(ea_endpoint->ep_join_id);
3953 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3956 if (our_join->j_type != JOIN_TYPE_PBX)
3958 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: join is not a pbx join.\n", ea_endpoint->ep_serial);
3961 our_joinpbx = (class JoinPBX *)our_join;
3962 if (!ea_endpoint->ep_portlist)
3964 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
3967 if (!e_ext.number[0])
3969 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
3972 our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
3975 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
3978 if ((our_port->p_type&PORT_CLASS_mISDN_MASK) != PORT_CLASS_mISDN_DSS1)
3980 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not isdn.\n", ea_endpoint->ep_serial);
3983 our_pdss1 = (class Pdss1 *)our_port;
3985 /* find an endpoint that is on hold and has the same mISDNport that we are on */
3986 other_eapp = apppbx_first;
3989 if (other_eapp == this)
3991 other_eapp = other_eapp->next;
3994 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);
3995 if (other_eapp->e_ext.number[0] /* has terminal */
3996 && other_eapp->ea_endpoint->ep_portlist /* has port */
3997 && other_eapp->ea_endpoint->ep_join_id) /* has join */
3999 other_port = find_port_id(other_eapp->ea_endpoint->ep_portlist->port_id);
4000 if (other_port) /* port still exists */
4002 if (other_port->p_type==PORT_TYPE_DSS1_NT_OUT
4003 || other_port->p_type==PORT_TYPE_DSS1_NT_IN) /* port is isdn nt-mode */
4005 other_pdss1 = (class Pdss1 *)other_port;
4006 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);
4007 if (other_pdss1->p_m_hold /* port is on hold */
4008 && other_pdss1->p_m_mISDNport == our_pdss1->p_m_mISDNport /* same isdn interface */
4009 && other_pdss1->p_m_d_ces == our_pdss1->p_m_d_ces) /* same tei+sapi */
4013 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of other type!\n", ea_endpoint->ep_serial);
4017 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port doesn't exist enymore.\n", ea_endpoint->ep_serial);
4020 other_eapp = other_eapp->next;
4024 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn interface with port on hold.\n", ea_endpoint->ep_serial);
4027 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port on hold found.\n", ea_endpoint->ep_serial);
4029 /* if we have the same join */
4030 if (other_eapp->ea_endpoint->ep_join_id == ea_endpoint->ep_join_id)
4032 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we an the other have the same join.\n", ea_endpoint->ep_serial);
4035 other_join = find_join_id(other_eapp->ea_endpoint->ep_join_id);
4038 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
4041 if (other_join->j_type != JOIN_TYPE_PBX)
4043 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join is not a pbx join.\n", ea_endpoint->ep_serial);
4046 other_joinpbx = (class JoinPBX *)other_join;
4047 if (our_joinpbx->j_partyline && other_joinpbx->j_partyline)
4049 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both joins are partylines.\n", ea_endpoint->ep_serial);
4053 /* remove relation to endpoint for join on hold */
4054 other_relation = other_joinpbx->j_relation;
4055 other_relation_pointer = &other_joinpbx->j_relation;
4056 while(other_relation)
4058 if (other_relation->epoint_id == other_eapp->ea_endpoint->ep_serial)
4060 /* detach other endpoint on hold */
4061 *other_relation_pointer = other_relation->next;
4062 FREE(other_relation, sizeof(struct join_relation));
4064 other_relation = *other_relation_pointer;
4065 other_eapp->ea_endpoint->ep_join_id = NULL;
4069 /* change join/hold pointer of endpoint to the new join */
4070 temp_epoint = find_epoint_id(other_relation->epoint_id);
4073 if (temp_epoint->ep_join_id == other_join->j_serial)
4074 temp_epoint->ep_join_id = our_join->j_serial;
4077 other_relation_pointer = &other_relation->next;
4078 other_relation = other_relation->next;
4080 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint on hold removed, other enpoints on join relinked (to our join).\n", ea_endpoint->ep_serial);
4082 /* join call relations */
4083 our_relation = our_joinpbx->j_relation;
4084 our_relation_pointer = &our_joinpbx->j_relation;
4087 our_relation_pointer = &our_relation->next;
4088 our_relation = our_relation->next;
4090 *our_relation_pointer = other_joinpbx->j_relation;
4091 other_joinpbx->j_relation = NULL;
4092 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) relations joined.\n", ea_endpoint->ep_serial);
4094 /* release endpoint on hold */
4095 message = message_create(other_joinpbx->j_serial, other_eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
4096 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */
4097 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
4098 message_put(message);
4100 /* if we are not a partyline, we get partyline state from other join */
4101 our_joinpbx->j_partyline += other_joinpbx->j_partyline;
4103 /* remove empty join */
4105 PDEBUG(DEBUG_EPOINT, "EPOINT(%d)d-join completely removed!\n");
4107 /* mixer must update */
4108 our_joinpbx->j_updatebridge = 1; /* update mixer flag */
4110 /* we send a retrieve to that endpoint */
4111 // mixer will update the hold-state of the join and send it to the endpoints is changes
4115 /* check if we have an external call
4116 * this is used to check for encryption ability
4118 int EndpointAppPBX::check_external(char **errstr, class Port **port)
4120 struct join_relation *relation;
4122 class JoinPBX *joinpbx;
4123 class Endpoint *epoint;
4125 /* some paranoia check */
4126 if (!ea_endpoint->ep_portlist)
4128 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we have no port.\n", ea_endpoint->ep_serial);
4129 *errstr = "No Call";
4132 if (!e_ext.number[0])
4134 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we are not internal extension.\n", ea_endpoint->ep_serial);
4135 *errstr = "No Call";
4139 /* check if we have a join with 2 parties */
4140 join = find_join_id(ea_endpoint->ep_join_id);
4143 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have currently no join.\n", ea_endpoint->ep_serial);
4144 *errstr = "No Call";
4147 if (join->j_type != JOIN_TYPE_PBX)
4149 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join is not a pbx join.\n", ea_endpoint->ep_serial);
4150 *errstr = "No PBX Call";
4153 joinpbx = (class JoinPBX *)join;
4154 relation = joinpbx->j_relation;
4157 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no relation.\n", ea_endpoint->ep_serial);
4158 *errstr = "No Call";
4161 if (!relation->next)
4163 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd relation.\n", ea_endpoint->ep_serial);
4164 *errstr = "No Call";
4167 if (relation->next->next)
4169 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has more than two relations.\n", ea_endpoint->ep_serial);
4170 *errstr = "Err: Conference";
4173 if (relation->epoint_id == ea_endpoint->ep_serial)
4175 relation = relation->next;
4176 if (relation->epoint_id == ea_endpoint->ep_serial)
4178 PERROR("EPOINT(%d) SOFTWARE ERROR: both join relations are related to our endpoint.\n", ea_endpoint->ep_serial);
4179 *errstr = "Software Error";
4184 /* check remote port for external call */
4185 epoint = find_epoint_id(relation->epoint_id);
4188 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd endpoint.\n", ea_endpoint->ep_serial);
4189 *errstr = "No Call";
4192 if (!epoint->ep_portlist)
4194 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not port.\n", ea_endpoint->ep_serial);
4195 *errstr = "No Call";
4198 *port = find_port_id(epoint->ep_portlist->port_id);
4201 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has an none existing port.\n", ea_endpoint->ep_serial);
4202 *errstr = "No Call";
4205 if (((*port)->p_type&PORT_CLASS_mISDN_MASK)!=PORT_CLASS_mISDN_DSS1) /* port is not external isdn */
4207 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not an external port.\n", ea_endpoint->ep_serial);
4208 *errstr = "No Ext Call";
4211 if ((*port)->p_state != PORT_STATE_CONNECT)
4213 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint's port is not in connected state.\n", ea_endpoint->ep_serial);
4214 *errstr = "No Ext Connect";
4220 void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsigned long port_id, int dir)
4222 char *logtext = "unknown";
4225 switch(message_type)
4228 trace_header("SETUP", dir);
4229 if (dir == DIRECTION_OUT)
4230 add_trace("to", NULL, "CH(%lu)", port_id);
4231 if (dir == DIRECTION_IN)
4232 add_trace("from", NULL, "CH(%lu)", port_id);
4233 if (param->setup.callerinfo.extension[0])
4234 add_trace("extension", NULL, "%s", param->setup.callerinfo.extension);
4235 add_trace("caller id", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype));
4236 switch(param->setup.callerinfo.present)
4238 case INFO_PRESENT_RESTRICTED:
4239 add_trace("caller id", "present", "restricted");
4241 case INFO_PRESENT_ALLOWED:
4242 add_trace("caller id", "present", "allowed");
4245 add_trace("caller id", "present", "not available");
4247 if (param->setup.redirinfo.id[0])
4249 add_trace("redir'ing", "number", "%s", numberrize_callerinfo(param->setup.redirinfo.id, param->setup.redirinfo.ntype));
4250 switch(param->setup.redirinfo.present)
4252 case INFO_PRESENT_RESTRICTED:
4253 add_trace("redir'ing", "present", "restricted");
4255 case INFO_PRESENT_ALLOWED:
4256 add_trace("redir'ing", "present", "allowed");
4259 add_trace("redir'ing", "present", "not available");
4262 if (param->setup.dialinginfo.id[0])
4263 add_trace("dialing", NULL, "%s", param->setup.dialinginfo.id);
4267 case MESSAGE_OVERLAP:
4268 trace_header("SETUP ACKNOWLEDGE", dir);
4269 if (dir == DIRECTION_OUT)
4270 add_trace("to", NULL, "CH(%lu)", port_id);
4271 if (dir == DIRECTION_IN)
4272 add_trace("from", NULL, "CH(%lu)", port_id);
4276 case MESSAGE_PROCEEDING:
4277 trace_header("PROCEEDING", dir);
4278 if (dir == DIRECTION_OUT)
4279 add_trace("to", NULL, "CH(%lu)", port_id);
4280 if (dir == DIRECTION_IN)
4281 add_trace("from", NULL, "CH(%lu)", port_id);
4285 case MESSAGE_ALERTING:
4286 trace_header("ALERTING", dir);
4287 if (dir == DIRECTION_OUT)
4288 add_trace("to", NULL, "CH(%lu)", port_id);
4289 if (dir == DIRECTION_IN)
4290 add_trace("from", NULL, "CH(%lu)", port_id);
4294 case MESSAGE_CONNECT:
4295 trace_header("CONNECT", dir);
4296 if (dir == DIRECTION_OUT)
4297 add_trace("to", NULL, "CH(%lu)", port_id);
4298 if (dir == DIRECTION_IN)
4299 add_trace("from", NULL, "CH(%lu)", port_id);
4300 if (param->connectinfo.extension[0])
4301 add_trace("extension", NULL, "%s", param->connectinfo.extension);
4302 add_trace("connect id", "number", "%s", numberrize_callerinfo(param->connectinfo.id, param->connectinfo.ntype));
4303 switch(param->connectinfo.present)
4305 case INFO_PRESENT_RESTRICTED:
4306 add_trace("connect id", "present", "restricted");
4308 case INFO_PRESENT_ALLOWED:
4309 add_trace("connect id", "present", "allowed");
4312 add_trace("connect id", "present", "not available");
4317 case MESSAGE_DISCONNECT:
4318 case MESSAGE_RELEASE:
4319 if (message_type == MESSAGE_DISCONNECT)
4320 trace_header("DISCONNECT", dir);
4322 trace_header("RELEASE", dir);
4323 if (dir == DIRECTION_OUT)
4324 add_trace("to", NULL, "CH(%lu)", port_id);
4325 if (dir == DIRECTION_IN)
4326 add_trace("from", NULL, "CH(%lu)", port_id);
4327 add_trace("cause", "value", "%d", param->disconnectinfo.cause);
4328 switch(param->disconnectinfo.location)
4331 add_trace("cause", "location", "0-User");
4333 case LOCATION_PRIVATE_LOCAL:
4334 add_trace("cause", "location", "1-Local-PBX");
4336 case LOCATION_PUBLIC_LOCAL:
4337 add_trace("cause", "location", "2-Local-Exchange");
4339 case LOCATION_TRANSIT:
4340 add_trace("cause", "location", "3-Transit");
4342 case LOCATION_PUBLIC_REMOTE:
4343 add_trace("cause", "location", "4-Remote-PBX");
4345 case LOCATION_PRIVATE_REMOTE:
4346 add_trace("cause", "location", "5-Remote-Exchange");
4348 case LOCATION_INTERNATIONAL:
4349 add_trace("cause", "location", "7-International-Exchange");
4351 case LOCATION_BEYOND:
4352 add_trace("cause", "location", "10-Beyond-Interworking");
4355 add_trace("cause", "location", "%d", param->disconnectinfo.location);
4360 case MESSAGE_NOTIFY:
4361 switch(param->notifyinfo.notify)
4367 logtext = "USER_SUSPENDED";
4370 logtext = "BEARER_SERVICE_CHANGED";
4373 logtext = "USER_RESUMED";
4376 logtext = "CONFERENCE_ESTABLISHED";
4379 logtext = "CONFERENCE_DISCONNECTED";
4382 logtext = "OTHER_PARTY_ADDED";
4385 logtext = "ISOLATED";
4388 logtext = "REATTACHED";
4391 logtext = "OTHER_PARTY_ISOLATED";
4394 logtext = "OTHER_PARTY_REATTACHED";
4397 logtext = "OTHER_PARTY_SPLIT";
4400 logtext = "OTHER_PARTY_DISCONNECTED";
4403 logtext = "CONFERENCE_FLOATING";
4406 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
4409 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
4412 logtext = "CALL_IS_A_WAITING_CALL";
4415 logtext = "DIVERSION_ACTIVATED";
4418 logtext = "RESERVED_CT_1";
4421 logtext = "RESERVED_CT_2";
4424 logtext = "REVERSE_CHARGING";
4427 logtext = "REMOTE_HOLD";
4430 logtext = "REMOTE_RETRIEVAL";
4433 logtext = "CALL_IS_DIVERTING";
4436 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
4440 trace_header("NOTIFY", dir);
4441 if (dir == DIRECTION_OUT)
4442 add_trace("to", NULL, "CH(%lu)", port_id);
4443 if (dir == DIRECTION_IN)
4444 add_trace("from", NULL, "CH(%lu)", port_id);
4445 if (param->notifyinfo.notify)
4446 add_trace("indicator", NULL, "%s", logtext);
4447 if (param->notifyinfo.id[0])
4449 add_trace("redir'on", "number", "%s", numberrize_callerinfo(param->notifyinfo.id, param->notifyinfo.ntype));
4450 switch(param->notifyinfo.present)
4452 case INFO_PRESENT_RESTRICTED:
4453 add_trace("redir'on", "present", "restricted");
4455 case INFO_PRESENT_ALLOWED:
4456 add_trace("redir'on", "present", "allowed");
4459 add_trace("redir'on", "present", "not available");
4462 if (param->notifyinfo.display[0])
4463 add_trace("display", NULL, "%s", param->notifyinfo.display);
4467 case MESSAGE_INFORMATION:
4468 trace_header("INFORMATION", dir);
4469 if (dir == DIRECTION_OUT)
4470 add_trace("to", NULL, "CH(%lu)", port_id);
4471 if (dir == DIRECTION_IN)
4472 add_trace("from", NULL, "CH(%lu)", port_id);
4473 add_trace("dialing", NULL, "%s", param->information.id);
4477 case MESSAGE_FACILITY:
4478 trace_header("FACILITY", dir);
4479 if (dir == DIRECTION_OUT)
4480 add_trace("to", NULL, "CH(%lu)", port_id);
4481 if (dir == DIRECTION_IN)
4482 add_trace("from", NULL, "CH(%lu)", port_id);
4487 trace_header("TONE", dir);
4488 if (dir == DIRECTION_OUT)
4489 add_trace("to", NULL, "CH(%lu)", port_id);
4490 if (dir == DIRECTION_IN)
4491 add_trace("from", NULL, "CH(%lu)", port_id);
4492 if (param->tone.name[0])
4494 add_trace("directory", NULL, "%s", param->tone.dir[0]?param->tone.dir:"default");
4495 add_trace("name", NULL, "%s", param->tone.name);
4497 add_trace("off", NULL, NULL);
4501 case MESSAGE_SUSPEND:
4502 case MESSAGE_RESUME:
4503 if (message_type == MESSAGE_SUSPEND)
4504 trace_header("SUSPEND", dir);
4506 trace_header("RESUME", dir);
4507 if (dir == DIRECTION_OUT)
4508 add_trace("to", NULL, "CH(%lu)", port_id);
4509 if (dir == DIRECTION_IN)
4510 add_trace("from", NULL, "CH(%lu)", port_id);
4511 if (param->parkinfo.len)
4512 add_trace("length", NULL, "%d", param->parkinfo.len);
4517 case MESSAGE_BCHANNEL:
4518 trace_header("BCHANNEL", dir);
4519 switch(param->bchannel.type)
4521 case BCHANNEL_REQUEST:
4522 add_trace("type", NULL, "request");
4524 case BCHANNEL_ASSIGN:
4525 add_trace("type", NULL, "assign");
4527 case BCHANNEL_ASSIGN_ACK:
4528 add_trace("type", NULL, "assign_ack");
4530 case BCHANNEL_REMOVE:
4531 add_trace("type", NULL, "remove");
4533 case BCHANNEL_REMOVE_ACK:
4534 add_trace("type", NULL, "remove_ack");
4537 if (param->bchannel.addr)
4538 add_trace("address", NULL, "%x", param->bchannel.addr);
4544 PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message_type);
4548 void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cause, int location, char *display)
4550 struct message *message;
4554 if (!portlist->port_id)
4557 if (!e_connectedmode)
4559 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT);
4560 message->param.disconnectinfo.cause = cause;
4561 message->param.disconnectinfo.location = location;
4563 SCPY(message->param.disconnectinfo.display, display);
4565 SCPY(message->param.disconnectinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4568 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
4570 SCPY(message->param.notifyinfo.display, display);
4572 SCPY(message->param.notifyinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4574 message_put(message);
4575 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);