X-Git-Url: http://git.eversberg.eu/gitweb.cgi?p=lcr.git;a=blobdiff_plain;f=action.cpp;h=5b332c9f0a437a6010abecfd3280254b74d15c34;hp=51aa8dbea1c8ba3ac9df5b927c78bca40368330d;hb=refs%2Fheads%2Fbackup2;hpb=2ed0fee489c37a6e2d4473f6185ebbe3e746ac11 diff --git a/action.cpp b/action.cpp index 51aa8db..5b332c9 100644 --- a/action.cpp +++ b/action.cpp @@ -9,102 +9,32 @@ ** ** \*****************************************************************************/ -#include -#include -#include -#include -#include #include "main.h" -#include "linux/isdnif.h" extern char **environ; -/* create caller id from digits by comparing with national and international - * prefixes. - */ -char *nationalize_callerinfo(char *string, int *ntype) -{ - if (!strncmp(options.international, string, strlen(options.international))) - { - *ntype = INFO_NTYPE_INTERNATIONAL; - return(string+strlen(options.international)); - } - if (!strncmp(options.national, string, strlen(options.national))) - { - *ntype = INFO_NTYPE_NATIONAL; - return(string+strlen(options.national)); - } - *ntype = INFO_NTYPE_SUBSCRIBER; - return(string); -} - -/* create number (including access codes) from caller id - * prefixes. - */ -char *numberrize_callerinfo(char *string, int ntype) -{ - static char result[256]; - - switch(ntype) - { - case INFO_NTYPE_INTERNATIONAL: - UCPY(result, options.international); - SCAT(result, string); - return(result); - break; - - case INFO_NTYPE_NATIONAL: - UCPY(result, options.national); - SCAT(result, string); - return(result); - break; - - default: - return(string); - } -} - - /* - * process init 'internal' / 'external' / 'h323' / 'chan' / 'vbox-record' / 'partyline'... + * process init 'internal' / 'external' / 'vbox-record' / 'partyline'... */ -void EndpointAppPBX::_action_init_call(int chan) +void EndpointAppPBX::action_init_call(void) { - class Call *call; - struct port_list *portlist = ea_endpoint->ep_portlist; + class Join *join; /* a created call, this should never happen */ - if (ea_endpoint->ep_call_id) - { + if (ea_endpoint->ep_join_id) { if (options.deb & DEBUG_EPOINT) PERROR("EPOINT(%d): We already have a call instance, this should never happen!\n", ea_endpoint->ep_serial); return; } - /* create call */ - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): Creating new call instance.\n", ea_endpoint->ep_serial); - if (chan) - call = new CallChan(ea_endpoint); - else - call = new CallPBX(ea_endpoint); - if (!call) - { - /* resource not available */ - message_disconnect_port(portlist, CAUSE_RESSOURCEUNAVAIL, LOCATION_PRIVATE_LOCAL, ""); - new_state(EPOINT_STATE_OUT_DISCONNECT); - set_tone(portlist,"cause_22"); - return; - } - ea_endpoint->ep_call_id = call->c_serial; -} -void EndpointAppPBX::action_init_call(void) -{ - _action_init_call(0); -} -void EndpointAppPBX::action_init_chan(void) -{ - _action_init_call(1); + /* create join */ + PDEBUG(DEBUG_EPOINT, "EPOINT(%d): Creating new join instance.\n", ea_endpoint->ep_serial); + join = new JoinPBX(ea_endpoint); + if (!join) + FATAL("No memoy for Join instance.\n"); + ea_endpoint->ep_join_id = join->j_serial; + return; } /* @@ -115,9 +45,10 @@ void EndpointAppPBX::action_dialing_internal(void) struct capa_info capainfo; struct caller_info callerinfo; struct redir_info redirinfo; + struct rtp_info rtpinfo; struct dialing_info dialinginfo; struct port_list *portlist = ea_endpoint->ep_portlist; - struct message *message; + struct lcr_msg *message; struct extension ext; struct route_param *rparam; @@ -125,87 +56,88 @@ void EndpointAppPBX::action_dialing_internal(void) set_tone(portlist, "proceeding"); message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING); message_put(message); - logmessage(message); + logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT); new_state(EPOINT_STATE_IN_PROCEEDING); /* create bearer/caller/dialinginfo */ memcpy(&capainfo, &e_capainfo, sizeof(capainfo)); memcpy(&callerinfo, &e_callerinfo, sizeof(callerinfo)); memcpy(&redirinfo, &e_redirinfo, sizeof(redirinfo)); + memcpy(&rtpinfo, &e_rtpinfo, sizeof(rtpinfo)); memset(&dialinginfo, 0, sizeof(dialinginfo)); - dialinginfo.itype = INFO_ITYPE_INTERN; - SCPY(dialinginfo.number, e_dialinginfo.number); + dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION; + SCPY(dialinginfo.id, e_dialinginfo.id); /* process extension */ if ((rparam = routeparam(e_action, PARAM_EXTENSION))) - SCPY(dialinginfo.number, rparam->string_value); + SCPY(dialinginfo.id, rparam->string_value); /* process number type */ if ((rparam = routeparam(e_action, PARAM_TYPE))) dialinginfo.ntype = rparam->integer_value; /* process service */ - if ((rparam = routeparam(e_action, PARAM_CAPA))) - { + if ((rparam = routeparam(e_action, PARAM_CAPA))) { capainfo.bearer_capa = rparam->integer_value; if (capainfo.bearer_capa != INFO_BC_SPEECH - && capainfo.bearer_capa != INFO_BC_AUDIO) - { + && capainfo.bearer_capa != INFO_BC_AUDIO) { capainfo.bearer_mode = INFO_BMODE_PACKET; } capainfo.bearer_info1 = INFO_INFO1_NONE; + capainfo.hlc = INFO_HLC_NONE; + capainfo.exthlc = INFO_HLC_NONE; } - if ((rparam = routeparam(e_action, PARAM_BMODE))) - { + if ((rparam = routeparam(e_action, PARAM_BMODE))) { capainfo.bearer_mode = rparam->integer_value; } - if ((rparam = routeparam(e_action, PARAM_INFO1))) - { + if ((rparam = routeparam(e_action, PARAM_INFO1))) { capainfo.bearer_info1 = rparam->integer_value; } - if ((rparam = routeparam(e_action, PARAM_HLC))) - { + if ((rparam = routeparam(e_action, PARAM_HLC))) { capainfo.hlc = rparam->integer_value; } - if ((rparam = routeparam(e_action, PARAM_EXTHLC))) - { + if ((rparam = routeparam(e_action, PARAM_EXTHLC))) { capainfo.exthlc = rparam->integer_value; } /* process presentation */ - if ((rparam = routeparam(e_action, PARAM_PRESENT))) - { + if ((rparam = routeparam(e_action, PARAM_PRESENT))) { callerinfo.present = (rparam->integer_value)?INFO_PRESENT_ALLOWED:INFO_PRESENT_RESTRICTED; } /* check if extension exists AND only if not multiple extensions */ - if (!read_extension(&ext, dialinginfo.number) && !strchr(dialinginfo.number,',')) - { - printlog("%3d action INTERN dialed extension %s doesn't exist.\n", ea_endpoint->ep_serial, dialinginfo.number); - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): extension %s doesn't exist\n", ea_endpoint->ep_serial, dialinginfo.number); + if (!strchr(dialinginfo.id,',') && !read_extension(&ext, dialinginfo.id)) { + trace_header("ACTION extension (extension doesn't exist)", DIRECTION_NONE); + add_trace("extension", NULL, dialinginfo.id); + end_trace(); + release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0, 0, 0); new_state(EPOINT_STATE_OUT_DISCONNECT); message_disconnect_port(portlist, CAUSE_UNALLOCATED, LOCATION_PRIVATE_LOCAL, ""); set_tone(portlist, "cause_86"); return; } /* check if internal calls are denied */ - if (e_ext.rights < 1) - { - printlog("%3d action INTERN access to internal phones are denied for this caller.\n", ea_endpoint->ep_serial); - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): internal call from terminal %s denied.\n", ea_endpoint->ep_serial, e_terminal); + if (e_ext.rights < 1) { + trace_header("ACTION extension (dialing to extension denied)", DIRECTION_NONE); + add_trace("extension", NULL, dialinginfo.id); + end_trace(); new_state(EPOINT_STATE_OUT_DISCONNECT); + release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0, 0, 0); message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, ""); set_tone(portlist, "cause_81"); return; } /* add or update internal call */ - printlog("%3d action INTERN call to extension %s.\n", ea_endpoint->ep_serial, dialinginfo.number); - message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_SETUP); + trace_header("ACTION extension (calling)", DIRECTION_NONE); + add_trace("extension", NULL, dialinginfo.id); + end_trace(); + message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_SETUP); memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info)); memcpy(&message->param.setup.redirinfo, &redirinfo, sizeof(struct redir_info)); memcpy(&message->param.setup.callerinfo, &callerinfo, sizeof(struct caller_info)); memcpy(&message->param.setup.capainfo, &capainfo, sizeof(struct capa_info)); + memcpy(&message->param.setup.rtpinfo, &rtpinfo, sizeof(struct rtp_info)); message_put(message); } @@ -216,36 +148,32 @@ void EndpointAppPBX::action_dialing_external(void) struct capa_info capainfo; struct caller_info callerinfo; struct redir_info redirinfo; + struct rtp_info rtpinfo; struct dialing_info dialinginfo; char *p; struct port_list *portlist = ea_endpoint->ep_portlist; - struct message *message; + struct lcr_msg *message; struct route_param *rparam; /* special processing of delete characters '*' and '#' */ - if (e_ext.delete_ext) - { + if (e_ext.delete_ext) { /* dialing a # causes a clearing of complete number */ - if (strchr(e_extdialing, '#')) - { + if (strchr(e_extdialing, '#')) { e_extdialing[0] = '\0'; - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): '#' detected: terminal '%s' selected caller id '%s' and continues dialing: '%s'\n", ea_endpoint->ep_serial, e_terminal, e_callerinfo.id, e_extdialing); + PDEBUG(DEBUG_EPOINT, "EPOINT(%d): '#' detected: terminal '%s' selected caller id '%s' and continues dialing: '%s'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, e_extdialing); } /* eliminate digits before '*', which is a delete digit */ - if (strchr(e_extdialing, '*')) - { + if (strchr(e_extdialing, '*')) { /* remove digits */ - while((p=strchr(e_extdialing, '*'))) - { - if (p > e_extdialing) /* only if there is a digit in front */ - { + while((p=strchr(e_extdialing, '*'))) { + if (p > e_extdialing) { /* only if there is a digit in front */ UCPY(p-1, p); p--; } UCPY(p, p+1); /* remove '*' */ } - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s deleted digits and got new string: %s\n", ea_endpoint->ep_serial, e_terminal, e_extdialing); + PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s deleted digits and got new string: %s\n", ea_endpoint->ep_serial, e_ext.number, e_extdialing); } } @@ -253,19 +181,27 @@ void EndpointAppPBX::action_dialing_external(void) memcpy(&capainfo, &e_capainfo, sizeof(capainfo)); memcpy(&callerinfo, &e_callerinfo, sizeof(callerinfo)); memcpy(&redirinfo, &e_redirinfo, sizeof(redirinfo)); + memcpy(&rtpinfo, &e_rtpinfo, sizeof(rtpinfo)); memset(&dialinginfo, 0, sizeof(dialinginfo)); - dialinginfo.itype = INFO_ITYPE_EXTERN; - dialinginfo.sending_complete = 0; - SCPY(dialinginfo.number, e_extdialing); + dialinginfo.itype = INFO_ITYPE_ISDN; +// dialinginfo.sending_complete = 0; + SCPY(dialinginfo.id, e_extdialing); /* process prefix */ if ((rparam = routeparam(e_action, PARAM_PREFIX))) - SPRINT(dialinginfo.number, "%s%s", rparam->string_value, e_extdialing); + SPRINT(dialinginfo.id, "%s%s", rparam->string_value, e_extdialing); + + if ((rparam = routeparam(e_action, PARAM_CONTEXT))) + SCPY(dialinginfo.context, rparam->string_value); + + /* process keypad */ + if ((rparam = routeparam(e_action, PARAM_KEYPAD))) { + SCPY(dialinginfo.keypad, dialinginfo.id); + dialinginfo.id[0] = '\0'; + } /* process number complete */ if ((rparam = routeparam(e_action, PARAM_COMPLETE))) - if ((rparam = routeparam(e_action, PARAM_PREFIX))) - SCPY(dialinginfo.number, rparam->string_value); dialinginfo.sending_complete = 1; /* process number type */ @@ -273,47 +209,40 @@ void EndpointAppPBX::action_dialing_external(void) dialinginfo.ntype = rparam->integer_value; /* process service */ - if ((rparam = routeparam(e_action, PARAM_CAPA))) - { + if ((rparam = routeparam(e_action, PARAM_CAPA))) { capainfo.bearer_capa = rparam->integer_value; if (capainfo.bearer_capa != INFO_BC_SPEECH - && capainfo.bearer_capa != INFO_BC_AUDIO) - { + && capainfo.bearer_capa != INFO_BC_AUDIO) { capainfo.bearer_mode = INFO_BMODE_PACKET; } capainfo.bearer_info1 = INFO_INFO1_NONE; + capainfo.hlc = INFO_HLC_NONE; + capainfo.exthlc = INFO_HLC_NONE; } - if ((rparam = routeparam(e_action, PARAM_BMODE))) - { + if ((rparam = routeparam(e_action, PARAM_BMODE))) { capainfo.bearer_mode = rparam->integer_value; } - if ((rparam = routeparam(e_action, PARAM_INFO1))) - { + if ((rparam = routeparam(e_action, PARAM_INFO1))) { capainfo.bearer_info1 = rparam->integer_value; } - if ((rparam = routeparam(e_action, PARAM_HLC))) - { + if ((rparam = routeparam(e_action, PARAM_HLC))) { capainfo.hlc = rparam->integer_value; } - if ((rparam = routeparam(e_action, PARAM_EXTHLC))) - { + if ((rparam = routeparam(e_action, PARAM_EXTHLC))) { capainfo.exthlc = rparam->integer_value; } /* process callerid */ - if ((rparam = routeparam(e_action, PARAM_CALLERID))) - { + if ((rparam = routeparam(e_action, PARAM_CALLERID))) { SCPY(callerinfo.id, rparam->string_value); } - if ((rparam = routeparam(e_action, PARAM_CALLERIDTYPE))) - { + if ((rparam = routeparam(e_action, PARAM_CALLERIDTYPE))) { callerinfo.ntype = rparam->integer_value; } /* process presentation */ - if ((rparam = routeparam(e_action, PARAM_PRESENT))) - { + if ((rparam = routeparam(e_action, PARAM_PRESENT))) { callerinfo.present = (rparam->integer_value)?INFO_PRESENT_ALLOWED:INFO_PRESENT_RESTRICTED; } @@ -322,11 +251,10 @@ void EndpointAppPBX::action_dialing_external(void) SCPY(dialinginfo.interfaces, rparam->string_value); /* check if local calls are denied */ - if (e_ext.rights < 2) - { - printlog("%3d action EXTERN calls are denied for this caller.\n", ea_endpoint->ep_serial); - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): external call from terminal denied: %s\n", ea_endpoint->ep_serial, e_terminal); - release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, 0); + if (e_ext.rights < 2) { + trace_header("ACTION extern (calling denied)", DIRECTION_NONE); + end_trace(); + release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_REJECTED, 0, 0, 0); set_tone(portlist, "cause_82"); denied: message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, ""); @@ -334,483 +262,49 @@ void EndpointAppPBX::action_dialing_external(void) return; } - if (!strncmp(dialinginfo.number, options.national, strlen(options.national)) + if (!strncmp(dialinginfo.id, options.national, strlen(options.national)) || dialinginfo.ntype == INFO_NTYPE_NATIONAL - || dialinginfo.ntype == INFO_NTYPE_INTERNATIONAL) - { + || dialinginfo.ntype == INFO_NTYPE_INTERNATIONAL) { /* check if national calls are denied */ - if (e_ext.rights < 3) - { - printlog("%3d action EXTERN national calls are denied for this caller.\n", ea_endpoint->ep_serial); - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): national call from terminal %s denied.\n", ea_endpoint->ep_serial, e_terminal); - release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, 0); + if (e_ext.rights < 3) { + trace_header("ACTION extern (national calls denied)", DIRECTION_NONE); + end_trace(); + release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_REJECTED, 0, 0, 0); set_tone(portlist, "cause_83"); goto denied; } } - if (!strncmp(dialinginfo.number, options.international, strlen(options.international)) - || dialinginfo.ntype == INFO_NTYPE_INTERNATIONAL) - { + if (!strncmp(dialinginfo.id, options.international, strlen(options.international)) + || dialinginfo.ntype == INFO_NTYPE_INTERNATIONAL) { /* check if international calls are denied */ - if (e_ext.rights < 4) - { - printlog("%3d action EXTERN international calls are denied for this caller.\n", ea_endpoint->ep_serial); - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): international call from terminal %s denied.\n", ea_endpoint->ep_serial, e_terminal); - release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, 0); + if (e_ext.rights < 4) { + trace_header("ACTION extern (international calls denied)", DIRECTION_NONE); + end_trace(); + release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_REJECTED, 0, 0, 0); set_tone(portlist, "cause_84"); goto denied; } } /* add or update outgoing call */ - printlog("%3d action EXTERN call to destination %s.\n", ea_endpoint->ep_serial, dialinginfo.number); - message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_SETUP); + trace_header("ACTION extern (calling)", DIRECTION_NONE); + add_trace("number", NULL, dialinginfo.id); + if (dialinginfo.sending_complete) + add_trace("number", "complete", "yes"); + if (dialinginfo.interfaces[0]) + add_trace("interfaces", NULL, dialinginfo.interfaces); + end_trace(); + message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_SETUP); memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info)); memcpy(&message->param.setup.redirinfo, &redirinfo, sizeof(struct redir_info)); memcpy(&message->param.setup.callerinfo, &callerinfo, sizeof(struct caller_info)); memcpy(&message->param.setup.capainfo, &capainfo, sizeof(struct capa_info)); + memcpy(&message->param.setup.rtpinfo, &rtpinfo, sizeof(struct rtp_info)); message_put(message); } -#ifdef H323 -/* - * process dialing h323 - */ -#define set_ip_macro \ - UNCPY(helpbuffer, address, sizeof(helpbuffer)); \ - helpbuffer[sizeof(helpbuffer)-1] = '\0'; \ - UNPRINT(helpbuffer + (int)(address - dial), sizeof(helpbuffer)-1 - (int)(address - dial), "%d.%d.%d.%d", ip_a, ip_b, ip_c, ip_d); \ - ii = strlen(helpbuffer); \ - UNCAT(helpbuffer, dial+i, sizeof(helpbuffer)-1); \ - dial = address + ii; \ - i = 0; \ - UCPY(address, helpbuffer); -#define set_port_macro \ - UNCPY(helpbuffer, address, sizeof(helpbuffer)); \ - helpbuffer[sizeof(helpbuffer)-1] = '\0'; \ - UNPRINT(helpbuffer + (int)(address - dial), sizeof(helpbuffer)-1 - (int)(address - dial), "%d", port); \ - ii = strlen(helpbuffer); \ - UNCAT(helpbuffer, dial+i, sizeof(helpbuffer)-1); \ - dial = address + ii; \ - i = 0; \ - UCPY(address, helpbuffer); -void EndpointAppPBX::action_dialing_h323(void) -{ - struct message *message; - struct dialing_info dialinginfo; - int i,j, ii; - struct port_list *portlist = ea_endpoint->ep_portlist; - char *dial; - char address_buffer[256], *address=address_buffer; - char host[128] = ""; - int ip_a=0, ip_b=0, ip_c=0, ip_d=0, port=0; - struct route_param *rparam; - char helpbuffer[128]; - - /* check if address parameter is given */ - if ((rparam = routeparam(e_action, PARAM_ADDRESS))) - { - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): complete address is given by parameter: '%s'\n", ea_endpoint->ep_serial, rparam->string_value); - SCPY(address_buffer, rparam->string_value); - goto address_complete; - } - - /* check for given host */ - if ((rparam = routeparam(e_action, PARAM_HOST))) - if (rparam->string_value[0]) - { - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): host is given by parameter: '%s'\n", ea_endpoint->ep_serial, rparam->string_value); - SCPY(host, rparam->string_value); - if ((rparam = routeparam(e_action, PARAM_PORT))) - { - if (rparam->integer_value>0 && rparam->integer_value<65536) - { - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): port is given with the host by parameter: %d\n", ea_endpoint->ep_serial, rparam->integer_value); - if (strlen(host)+7 < sizeof(host)) - UPRINT(host, ":%d/", rparam->integer_value); - } else - { - SCAT(host, "/"); - } - } else - { - SCAT(host, "/"); - } - } - - /* include prefix and put 'host'(port) in front */ - if ((rparam = routeparam(e_action, PARAM_PREFIX))) - { - SPRINT(address_buffer, "%s%s%s", host, rparam->string_value, e_extdialing); - } else - { - if (host[0]) - { - SPRINT(address_buffer, "%s%s", host, e_extdialing); - printf("address:%s host %s extdialing %s\n",address,host, e_extdialing); - } else { - address = e_extdialing; - } - } - dial = address; - - /* check dialing */ - /* check for ip-number only with numerical digits (can be dialed by any phone) */ - if (host[0]) - { - dial = address + strlen(host); - goto check_user; /* we have complete host (port) */ - } - i = 0; - while(i < 12) - { - if (dial[i] == '\0') - return; /* unfinished */ - if (dial[i]<'0' || dial[i]>'9') - goto check_complex; - i++; - - if (i == 3) - { - ip_a = (dial[0]-'0')*100 + (dial[1]-'0')*10 + (dial[2]-'0'); - if (ip_a > 255) - { - invalid: - printlog("%3d action H323 address '%s' is invalid.\n", ea_endpoint->ep_serial, address); - message_disconnect_port(portlist, CAUSE_INVALID, LOCATION_PRIVATE_LOCAL, ""); - new_state(EPOINT_STATE_OUT_DISCONNECT); - set_tone(portlist,"cause_1c"); - return; - } - } - if (i == 6) - { - ip_b = (dial[3]-'0')*100 + (dial[4]-'0')*10 + (dial[5]-'0'); - if (ip_b > 255) - goto invalid; - } - if (i == 9) - { - ip_c = (dial[6]-'0')*100 + (dial[7]-'0')*10 + (dial[8]-'0'); - if (ip_c > 255) - goto invalid; - } - if (i == 12) - { - ip_d = (dial[9]-'0')*100 + (dial[10]-'0')*10 + (dial[11]-'0'); - if (ip_d > 255) - goto invalid; - } - if (i==4 || i==7 || i==10) - { - if (dial[i-1] > '2') - goto invalid; - } - if (i==5 || i==8 || i==11) - { - if (dial[i-2]=='2' && dial[i-1]>'5') - goto invalid; - } - } - UPRINT(address, "%d.%d.%d.%d", ip_a, ip_b, ip_c, ip_d); - i = strlen(address); - goto address_complete; - - /* there are three stages of dialing: 1. ip, 2. port, 3. user, let's find out where we at */ - check_complex: - if (strchr(address, '@')) - { - dial = strchr(address, '\0'); - goto address_complete; - } - if (strchr(address, ':')) - { - dial = strchr(address, ':') + 1; - goto check_port; - } - if (strchr(address, '/')) - { - dial = strchr(address, '/') + 1; - goto check_user; - } - - /* get ip from ip-number */ - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): checking dialed for ip: %s\n", ea_endpoint->ep_serial, dial); - ip_a = ip_b = ip_c = ip_d = 0; - i = 0; - j = 0; - while(42) - { - if (j==4) - goto invalid; - if (ip_a > 255) - goto invalid; - if (dial[i]>='0' && dial[i]<='9') - ip_a = (ip_a*10) + dial[i]-'0'; - else if (dial[i]=='.' || dial[i]=='*') - { - dial[i] = '.'; -// if (i && dial[i-1]=='.') -// { -// /* add 0 if two dots */ -// UCPY(dial+i+1, dial+i); -// dial[i]='0'; -// i++; -// } - i++; - break; - } - else if (dial[i]=='#') - { - ip_d = ip_a; - ip_a = 0; - set_ip_macro - i++; - dial+= i; - goto address_complete; - } - else if (dial[i] == '\0') - { - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): ip so far: %d*\n", ea_endpoint->ep_serial, ip_a); - return; - } - else - goto invalid; - i++; - j++; - } - j = 0; - while(42) - { - if (j==4) - goto invalid; - if (ip_b > 255) - goto invalid; - if (dial[i]>='0' && dial[i]<='9') - ip_b = (ip_b*10) + dial[i]-'0'; - else if (dial[i]=='.' || dial[i]=='*') - { - dial[i] = '.'; - i++; - break; - } - else if (dial[i]=='#') - { - ip_d = ip_b; - ip_b = 0; - set_ip_macro - i++; - dial+= i; - goto address_complete; - } - else if (dial[i] == '\0') - { - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): ip so far: %d.%d*\n", ea_endpoint->ep_serial, ip_a, ip_b); - return; - } - else - goto invalid; - i++; - j++; - } - j = 0; - while(42) - { - if (j==4) - goto invalid; - if (ip_c > 255) - goto invalid; - if (dial[i]>='0' && dial[i]<='9') - ip_c = (ip_c*10) + dial[i]-'0'; - else if (dial[i]=='.' || dial[i]=='*') - { - dial[i] = '.'; - i++; - break; - } - else if (dial[i]=='#') - { - ip_d = ip_c; - ip_c = 0; - set_ip_macro - i++; - dial+= i; - goto address_complete; - } - else if (dial[i] == '\0') - { - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): ip so far: %d.%d.%d\n", ea_endpoint->ep_serial, ip_a, ip_b, ip_c); - return; - } - else - goto invalid; - i++; - j++; - } - j = 0; - while(42) - { - if (j==4) - goto invalid; - if (ip_d > 255) - goto invalid; - if (dial[i]>='0' && dial[i]<='9') - ip_d = (ip_d*10) + dial[i]-'0'; - else if (dial[i]=='*' || dial[i]==':') - { - set_ip_macro - dial[i] = ':'; - i++; - dial+= i; - goto check_port; - } - else if (dial[i]=='#') - { - set_ip_macro - i++; - dial+= i; - goto address_complete; - } - else if (dial[i] == '\0') - { - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): ip so far: %d.%d.%d.%d*\n", ea_endpoint->ep_serial, ip_a, ip_b, ip_c, ip_d); - return; - } - else - goto invalid; - i++; - j++; - } - - /* get port */ - check_port: - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): checking dialed for port: %s\n", ea_endpoint->ep_serial, dial); - port = 0; - i = 0; - j = 0; - while(42) - { - if (j==6) - goto invalid; - if (port > 65535) - goto invalid; - if (dial[i]>='0' && dial[i]<='9') - port = (port*10) + dial[i]-'0'; - else if (dial[i]=='*' || dial[i]=='/') - { - if (i) /* only if there is something entered */ - { - set_port_macro - dial[i] = '/'; - } else - { - i--; - UCPY(dial+i, dial+i+1); - dial[i] = '/'; - } - i++; - dial+= i; - goto check_user; - } - else if (dial[i]=='#') - { - set_port_macro - i++; - dial+= i; - goto address_complete; - } - else if (dial[i] == '\0') - { - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): h323 address so far: %s\n", ea_endpoint->ep_serial, address); - return; - } - else - goto invalid; - i++; - j++; - } - - /* get user */ - check_user: - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): checking dialed for user: %s\n", ea_endpoint->ep_serial, dial); - port = 0; - i = 0; - j = 0; - while(42) - { - if (dial[i]=='#') - { - dial[i] = '\0'; - /* convert to @-notation */ - SCPY(helpbuffer, strchr(address, '/')+1); - SCAT(helpbuffer, "@"); - *strchr(address, '/') = '\0'; - SCAT(helpbuffer, address); - UCPY(address, helpbuffer); - goto address_complete; - } - else if (dial[i] == '\0') - { - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): h323 address so far: %s\n", ea_endpoint->ep_serial, address); - return; - } - i++; - j++; - } - - address_complete: - /* send proceeding, because number is complete */ - set_tone(portlist, "proceeding"); - message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING); - message_put(message); - logmessage(message); - new_state(EPOINT_STATE_IN_PROCEEDING); - - memset(&dialinginfo, 0, sizeof(dialinginfo)); - dialinginfo.itype = INFO_ITYPE_H323; - dialinginfo.sending_complete = 1; - SPRINT(dialinginfo.number, "%s", address); - /* strip the # at the end */ - if (dialinginfo.number[0]) - if (dialinginfo.number[strlen(dialinginfo.number)-1] == '#') - dialinginfo.number[strlen(dialinginfo.number)-1] = '\0'; - - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): complete multi-dial string \"%s\"\n", ea_endpoint->ep_serial, dialinginfo.number); - - /* add or update internal call */ - printlog("%3d action H323 call to address %s.\n", ea_endpoint->ep_serial, dialinginfo.number); - message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_SETUP); - memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info)); - memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info)); - memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info)); - memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info)); - message_put(message); -} -#else -void EndpointAppPBX::action_dialing_h323(void) -{ - struct port_list *portlist = ea_endpoint->ep_portlist; - - printlog("%3d action H323 stack not implemented.\n", ea_endpoint->ep_serial); - message_disconnect_port(portlist, CAUSE_UNIMPLEMENTED, LOCATION_PRIVATE_LOCAL, ""); - new_state(EPOINT_STATE_OUT_DISCONNECT); - set_tone(portlist,"cause_4f"); -} -#endif - -void EndpointAppPBX::action_dialing_chan(void) -{ - struct port_list *portlist = ea_endpoint->ep_portlist; - - printlog("%3d action channel API not implemented.\n", ea_endpoint->ep_serial); - message_disconnect_port(portlist, CAUSE_UNIMPLEMENTED, LOCATION_PRIVATE_LOCAL, ""); - new_state(EPOINT_STATE_OUT_DISCONNECT); - set_tone(portlist,"cause_4f"); -} - - /* * process dialing the "am" and record */ @@ -818,17 +312,16 @@ void EndpointAppPBX::action_dialing_vbox_record(void) { struct dialing_info dialinginfo; struct port_list *portlist = ea_endpoint->ep_portlist; - struct message *message; + struct lcr_msg *message; struct extension ext; struct route_param *rparam; portlist = ea_endpoint->ep_portlist; /* check for given extension */ - if (!(rparam = routeparam(e_action, PARAM_EXTENSION))) - { - printlog("%3d action VBOX-RECORD extension not given by parameter.\n", ea_endpoint->ep_serial); - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): cannot record, because no 'extension' parameter has been specified.\n", ea_endpoint->ep_serial); + if (!(rparam = routeparam(e_action, PARAM_EXTENSION))) { + trace_header("ACTION vbox-record (no extension given by parameter)", DIRECTION_NONE); + end_trace(); new_state(EPOINT_STATE_OUT_DISCONNECT); message_disconnect_port(portlist, CAUSE_SERVICEUNAVAIL, LOCATION_PRIVATE_LOCAL, ""); @@ -837,23 +330,20 @@ void EndpointAppPBX::action_dialing_vbox_record(void) } /* check if extension exists */ - if (!read_extension(&ext, rparam->string_value)) - { - printlog("%3d action VBOX-RECORD given extension %s doesn't exist.\n", ea_endpoint->ep_serial, rparam->string_value); - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): extension %s doesn't exist\n", ea_endpoint->ep_serial, rparam->string_value); + if (!read_extension(&ext, rparam->string_value)) { + trace_header("ACTION vbox-record (given extension does not exists)", DIRECTION_NONE); + add_trace("extension", NULL, "%s", rparam->string_value); + end_trace(); new_state(EPOINT_STATE_OUT_DISCONNECT); message_disconnect_port(portlist, CAUSE_UNALLOCATED, LOCATION_PRIVATE_LOCAL, ""); set_tone(portlist, "cause_86"); return; } - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s dialing extension: %s\n", ea_endpoint->ep_serial, e_terminal, rparam->string_value); - /* check if internal calls are denied */ - if (e_ext.rights < 1) - { - printlog("%3d action VBOX-RECORD calls are denied for this caller.\n", ea_endpoint->ep_serial); - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): internal call from terminal %s denied.\n", ea_endpoint->ep_serial, e_terminal); + if (e_ext.rights < 1) { + trace_header("ACTION vbox-record (internal calls are denied)", DIRECTION_NONE); + end_trace(); new_state(EPOINT_STATE_OUT_DISCONNECT); message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, ""); set_tone(portlist, "cause_81"); @@ -863,25 +353,26 @@ void EndpointAppPBX::action_dialing_vbox_record(void) set_tone(portlist, "proceeding"); message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING); message_put(message); - logmessage(message); + logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT); new_state(EPOINT_STATE_IN_PROCEEDING); memset(&dialinginfo, 0, sizeof(dialinginfo)); dialinginfo.itype = INFO_ITYPE_VBOX; dialinginfo.sending_complete = 1; - SCPY(dialinginfo.number, rparam->string_value); + SCPY(dialinginfo.id, rparam->string_value); /* append special announcement (if given) */ if ((rparam = routeparam(e_action, PARAM_ANNOUNCEMENT))) - if (rparam->string_value[0]) - { - SCAT(dialinginfo.number, ","); - SCAT(dialinginfo.number, rparam->string_value); + if (rparam->string_value[0]) { + SCAT(dialinginfo.id, ","); + SCAT(dialinginfo.id, rparam->string_value); } /* add or update internal call */ - printlog("%3d action VBOX-RECORD call to extension %s.\n", ea_endpoint->ep_serial, dialinginfo.number); - message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_SETUP); + trace_header("ACTION vbox-record (calling)", DIRECTION_NONE); + add_trace("extension", NULL, "%s", dialinginfo.id); + end_trace(); + message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_SETUP); memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info)); memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info)); memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info)); @@ -895,89 +386,80 @@ void EndpointAppPBX::action_dialing_vbox_record(void) */ void EndpointAppPBX::action_init_partyline(void) { - class Call *call; - class CallPBX *callpbx; + class Join *join; + class JoinPBX *joinpbx; struct port_list *portlist = ea_endpoint->ep_portlist; - struct message *message; + struct lcr_msg *message; struct route_param *rparam; - int partyline; - struct call_relation *relation; + int partyline, jingle = 0; + struct join_relation *relation; portlist = ea_endpoint->ep_portlist; /* check for given extension */ - if (!(rparam = routeparam(e_action, PARAM_ROOM))) - { - printlog("%3d action PARTYLINE no 'room' parameter given at routing.\n", ea_endpoint->ep_serial); - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): missing parameter 'room'.\n", ea_endpoint->ep_serial); + if (!(rparam = routeparam(e_action, PARAM_ROOM))) { + trace_header("ACTION partyline (no room parameter)", DIRECTION_NONE); + end_trace(); noroom: new_state(EPOINT_STATE_OUT_DISCONNECT); message_disconnect_port(portlist, CAUSE_SERVICEUNAVAIL, LOCATION_PRIVATE_LOCAL, ""); set_tone(portlist, "cause_3f"); return; } - if (rparam->integer_value <= 0) - { - printlog("%3d action PARTYLINE 'room' value must be greate 0.\n", ea_endpoint->ep_serial); + if (rparam->integer_value <= 0) { + trace_header("ACTION partyline (illegal room parameter)", DIRECTION_NONE); + add_trace("room", NULL, "%d", rparam->integer_value); + end_trace(); PDEBUG(DEBUG_EPOINT, "EPOINT(%d): invalid value for 'room'.\n", ea_endpoint->ep_serial); goto noroom; } partyline = rparam->integer_value; - - /* don't create call if partyline exists */ - call = call_first; - while(call) - { - if (call->c_type == CALL_TYPE_PBX) - { - callpbx = (class CallPBX *)call; - if (callpbx->c_partyline == rparam->integer_value) + if ((rparam = routeparam(e_action, PARAM_JINGLE))) + jingle = 1; + + /* don't create join if partyline exists */ + join = join_first; + while(join) { + if (join->j_type == JOIN_TYPE_PBX) { + joinpbx = (class JoinPBX *)join; + if (joinpbx->j_partyline == partyline) break; } - call = call->next; - } - if (!call) - { - /* create call */ - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): Creating new call instance.\n", ea_endpoint->ep_serial); - if (!(call = new CallPBX(ea_endpoint))) - { - nores: - /* resource not available */ - message_disconnect_port(portlist, CAUSE_RESSOURCEUNAVAIL, LOCATION_PRIVATE_LOCAL, ""); - new_state(EPOINT_STATE_OUT_DISCONNECT); - set_tone(portlist,"cause_22"); - return; - } - } else - { -//NOTE: callpbx must be set here - /* add relation to existing call */ - if (!(relation=callpbx->add_relation())) - { - goto nores; - } + join = join->next; + } + if (!join) { + /* create join */ + PDEBUG(DEBUG_EPOINT, "EPOINT(%d): Creating new join instance.\n", ea_endpoint->ep_serial); + if (!(join = new JoinPBX(ea_endpoint))) + FATAL("No memory for join object\n"); + } else { +//NOTE: joinpbx must be set here + /* add relation to existing join */ + if (!(relation=joinpbx->add_relation())) + FATAL("No memory for join relation\n"); relation->type = RELATION_TYPE_SETUP; - relation->channel_state = CHANNEL_STATE_CONNECT; + relation->channel_state = 1; relation->rx_state = NOTIFY_STATE_ACTIVE; relation->tx_state = NOTIFY_STATE_ACTIVE; relation->epoint_id = ea_endpoint->ep_serial; } - ea_endpoint->ep_call_id = call->c_serial; - - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s dialing room: %d\n", ea_endpoint->ep_serial, e_terminal, partyline); + ea_endpoint->ep_join_id = join->j_serial; set_tone(portlist, "proceeding"); message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING); message_put(message); - logmessage(message); + logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT); new_state(EPOINT_STATE_IN_PROCEEDING); - /* send setup to call */ - printlog("%3d action PARTYLINE call to room %d.\n", ea_endpoint->ep_serial, partyline); - message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_SETUP); + /* send setup to join */ + trace_header("ACTION partyline (calling)", DIRECTION_NONE); + add_trace("room", NULL, "%d", partyline); + add_trace("jingle", NULL, (jingle)?"on":"off"); + end_trace(); + message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_SETUP); message->param.setup.partyline = partyline; + message->param.setup.partyline_jingle = jingle; memcpy(&message->param.setup.dialinginfo, &e_dialinginfo, sizeof(struct dialing_info)); memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info)); memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info)); @@ -991,43 +473,8 @@ void EndpointAppPBX::action_init_partyline(void) */ void EndpointAppPBX::action_hangup_call(void) { - int i; - - printlog("%3d action CALL to '%s' hangs up.\n", ea_endpoint->ep_serial, e_dialinginfo.number); - /* check */ - if (e_terminal[0] == '\0') - { - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: cannot store last dialed number '%s' because caller is unknown (not internal).\n", ea_endpoint->ep_serial, e_terminal, e_dialinginfo.number); - return; - } - if (!(read_extension(&e_ext, e_terminal))) - { - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: cannot store last dialed number '%s' because cannot read settings.\n", ea_endpoint->ep_serial, e_terminal, e_dialinginfo.number); - return; - } - if (e_dialinginfo.number[0] == '\0') - { - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: cannot store last dialed number because nothing was dialed.\n", ea_endpoint->ep_serial, e_terminal); - return; - } - if (!strcmp(e_dialinginfo.number, e_ext.last_out[0])) - { - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: cannot store last dialed number '%s' because it is identical with the last one.\n", ea_endpoint->ep_serial, e_terminal, e_dialinginfo.number); - return; - } - - /* insert */ - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: storing last number '%s'.\n", ea_endpoint->ep_serial, e_terminal, e_dialinginfo.number); - i = MAX_REMEMBER-1; - while(i) - { - UCPY(e_ext.last_out[i], e_ext.last_out[i-1]); - i--; - } - SCPY(e_ext.last_out[0], e_dialinginfo.number); - - /* write extension */ - write_extension(&e_ext, e_terminal); + trace_header("ACTION hangup", DIRECTION_NONE); + end_trace(); } @@ -1037,43 +484,41 @@ void EndpointAppPBX::action_hangup_call(void) void EndpointAppPBX::action_dialing_login(void) { struct port_list *portlist = ea_endpoint->ep_portlist; - struct message *message; + struct lcr_msg *message; char *extension; struct route_param *rparam; /* extension parameter */ - if ((rparam = routeparam(e_action, PARAM_EXTENSION))) - { + if ((rparam = routeparam(e_action, PARAM_EXTENSION))) { /* extension is given by parameter */ extension = rparam->string_value; if (extension[0] == '\0') return; - if (!read_extension(&e_ext, extension)) - { - printlog("%3d action LOGIN given extension %s doesn't exist.\n", ea_endpoint->ep_serial, extension); - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): given extension %s not found.\n", ea_endpoint->ep_serial, extension); + if (!read_extension(&e_ext, extension)) { + trace_header("ACTION login (extension doesn't exist)", DIRECTION_NONE); + add_trace("extension", NULL, "%s", extension); + end_trace(); /* extension doesn't exist */ new_state(EPOINT_STATE_OUT_DISCONNECT); message_disconnect_port(portlist, CAUSE_UNALLOCATED, LOCATION_PRIVATE_LOCAL, ""); set_tone(portlist, "cause_86"); return; } - } else - { + } else { /* extension must be given by dialstring */ extension = e_extdialing; if (extension[0] == '\0') return; - if (!read_extension(&e_ext, extension)) - { - printlog("%3d action LOGIN given extension %s incomplete or not found..\n", ea_endpoint->ep_serial, extension); - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): extension %s incomplete or not found\n", ea_endpoint->ep_serial, extension); + if (!read_extension(&e_ext, extension)) { + trace_header("ACTION login (extension incomplete or does not exist)", DIRECTION_NONE); + add_trace("extension", NULL, "%s", extension); + end_trace(); return; } } /* we changed our extension */ - SCPY(e_terminal, extension); + SCPY(e_ext.number, extension); new_state(EPOINT_STATE_CONNECT); e_dtmf = 1; e_connectedmode = 1; @@ -1086,12 +531,12 @@ void EndpointAppPBX::action_dialing_login(void) message->param.connectinfo.present = INFO_PRESENT_RESTRICTED; else message->param.connectinfo.present = e_ext.callerid_present; /* handle restricted caller ids */ - apply_callerid_restriction(e_ext.anon_ignore, portlist->port_type, message->param.connectinfo.id, &message->param.connectinfo.ntype, &message->param.connectinfo.present, &message->param.connectinfo.screen, message->param.connectinfo.voip, message->param.connectinfo.intern, message->param.connectinfo.name); + apply_callerid_restriction(&e_ext, message->param.connectinfo.id, &message->param.connectinfo.ntype, &message->param.connectinfo.present, &message->param.connectinfo.screen, message->param.connectinfo.extension, message->param.connectinfo.name); /* display callerid if desired for extension */ - SCPY(message->param.connectinfo.display, apply_callerid_display(message->param.connectinfo.id, message->param.connectinfo.itype, message->param.connectinfo.ntype, message->param.connectinfo.present, message->param.connectinfo.screen, message->param.connectinfo.voip, message->param.connectinfo.intern, message->param.connectinfo.name)); + 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)); message->param.connectinfo.ntype = e_ext.callerid_type; message_put(message); - logmessage(message); + logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT); /* set our caller id */ SCPY(e_callerinfo.id, e_ext.callerid); @@ -1102,34 +547,34 @@ void EndpointAppPBX::action_dialing_login(void) e_connectedmode = 1; e_dtmf = 1; - if (!(rparam = routeparam(e_action, PARAM_NOPASSWORD))) - { + if (!(rparam = routeparam(e_action, PARAM_NOPASSWORD))) { /* make call state to enter password */ - printlog("%3d action LOGIN to extension %s, ask for password.\n", ea_endpoint->ep_serial, e_terminal); + trace_header("ACTION login (ask for password)", DIRECTION_NONE); + add_trace("extension", NULL, "%s", e_ext.number); + end_trace(); new_state(EPOINT_STATE_IN_OVERLAP); e_ruleset = NULL; e_rule = NULL; e_action = &action_password; - e_match_timeout = 0; + unsched_timer(&e_match_timeout); e_match_to_action = NULL; - e_dialinginfo.number[0] = '\0'; - e_extdialing = strchr(e_dialinginfo.number, '\0'); + e_dialinginfo.id[0] = '\0'; + e_extdialing = strchr(e_dialinginfo.id, '\0'); /* set timeout */ - e_password_timeout = now+20; + schedule_timer(&e_password_timeout, 20, 0); /* do dialing */ - process_dialing(); - } else - { + process_dialing(0); + } else { /* make call state */ new_state(EPOINT_STATE_IN_OVERLAP); e_ruleset = ruleset_main; if (e_ruleset) e_rule = e_ruleset->rule_first; e_action = NULL; - e_dialinginfo.number[0] = '\0'; - e_extdialing = e_dialinginfo.number; + e_dialinginfo.id[0] = '\0'; + e_extdialing = e_dialinginfo.id; set_tone(portlist, "dialpbx"); } } @@ -1142,10 +587,10 @@ void EndpointAppPBX::action_init_change_callerid(void) { struct port_list *portlist = ea_endpoint->ep_portlist; - if (!e_ext.change_callerid) - { + if (!e_ext.change_callerid) { /* service not available */ - printlog("%3d action CHANGE-CALLERID denied for this caller.\n", ea_endpoint->ep_serial); + trace_header("ACTION change-callerid (denied for this caller)", DIRECTION_NONE); + end_trace(); message_disconnect_port(portlist, CAUSE_SERVICEUNAVAIL, LOCATION_PRIVATE_LOCAL, ""); new_state(EPOINT_STATE_OUT_DISCONNECT); set_tone(portlist,"cause_87"); @@ -1160,16 +605,15 @@ void EndpointAppPBX::_action_callerid_calleridnext(int next) struct port_list *portlist = ea_endpoint->ep_portlist; struct route_param *rparam; char buffer[64], *callerid; + char old_id[64] = "", new_id[64] = ""; + int old_type=0, new_type=0, old_present=0, new_present=0; - if ((rparam = routeparam(e_action, PARAM_CALLERID))) - { + if ((rparam = routeparam(e_action, PARAM_CALLERID))) { /* the caller ID is given by parameter */ callerid = rparam->string_value; - } else - { + } else { /* caller ID is dialed */ - if (!strchr(e_extdialing, '#')) - { + if (!strchr(e_extdialing, '#')) { /* no complete ID yet */ return; } @@ -1179,8 +623,7 @@ void EndpointAppPBX::_action_callerid_calleridnext(int next) /* given callerid type */ if ((rparam = routeparam(e_action, PARAM_CALLERIDTYPE))) - switch(rparam->integer_value) - { + switch(rparam->integer_value) { case INFO_NTYPE_SUBSCRIBER: SPRINT(buffer, "s%s", callerid); callerid = buffer; @@ -1200,36 +643,44 @@ void EndpointAppPBX::_action_callerid_calleridnext(int next) } /* caller id complete, dialing with new caller id */ - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: storing callerid '%s' for all following calls.\n", ea_endpoint->ep_serial, e_terminal, callerid); /* write new parameters */ - if (read_extension(&e_ext, e_terminal)) - { - if (callerid[0] == '\0') - { + if (read_extension(&e_ext, e_ext.number)) { + old_present = (!next)?e_ext.callerid_present:e_ext.id_next_call_present; + old_type = (!next)?e_ext.callerid_type:e_ext.id_next_call_type; + SCPY(old_id, (!next)?e_ext.callerid:e_ext.id_next_call); + if (callerid[0] == '\0') { /* no caller id */ (!next)?e_ext.callerid_present:e_ext.id_next_call_present = INFO_PRESENT_RESTRICTED; - } else - { + } else { /* new caller id */ (!next)?e_ext.callerid_present:e_ext.id_next_call_present = INFO_PRESENT_ALLOWED; if ((rparam = routeparam(e_action, PARAM_PRESENT))) if (rparam->integer_value == 0) (!next)?e_ext.callerid_present:e_ext.id_next_call_present = INFO_PRESENT_RESTRICTED; - if (e_ext.callerid_type == INFO_NTYPE_UNKNOWN) /* if callerid is unknown, the given id is not nationalized */ - { + if (e_ext.callerid_type == INFO_NTYPE_UNKNOWN) /* if callerid is unknown, the given id is not nationalized */ { SCPY((!next)?e_ext.callerid:e_ext.id_next_call, callerid); (!next)?e_ext.callerid_type:e_ext.id_next_call_type = INFO_NTYPE_UNKNOWN; - } else - { - SCPY((!next)?e_ext.callerid:e_ext.id_next_call, nationalize_callerinfo(callerid,&((!next)?e_ext.callerid_type:e_ext.id_next_call_type))); + } else { + SCPY((!next)?e_ext.callerid:e_ext.id_next_call, nationalize_callerinfo(callerid,&((!next)?e_ext.callerid_type:e_ext.id_next_call_type), options.national, options.international)); } if (!next) e_ext.id_next_call_type = -1; PDEBUG(DEBUG_EPOINT, "EPOINT(%d): nationalized callerid: '%s' type=%d\n", ea_endpoint->ep_serial, (!next)?e_ext.callerid:e_ext.id_next_call, (!next)?e_ext.callerid_type:e_ext.id_next_call_type); } - write_extension(&e_ext, e_terminal); + new_present = (!next)?e_ext.callerid_present:e_ext.id_next_call_present; + new_type = (!next)?e_ext.callerid_type:e_ext.id_next_call_type; + SCPY(new_id, (!next)?e_ext.callerid:e_ext.id_next_call); + write_extension(&e_ext, e_ext.number); } /* function activated */ - printlog("%3d action CHANGE-CALLERID caller changes caller id%s to '%s'.\n", ea_endpoint->ep_serial, next?" of next call":"", callerid); + if (next) + trace_header("ACTION change-callerid (only next call)", DIRECTION_NONE); + else + trace_header("ACTION change-callerid (all future calls)", DIRECTION_NONE); + add_trace("old", "caller id", "%s", numberrize_callerinfo(old_id, old_type, options.national, options.international)); + add_trace("old", "present", "%s", (old_present==INFO_PRESENT_RESTRICTED)?"restricted":"allowed"); + add_trace("new", "caller id", "%s", numberrize_callerinfo(new_id, new_type, options.national, options.international)); + add_trace("new", "present", "%s", (new_present==INFO_PRESENT_RESTRICTED)?"restricted":"allowed"); + end_trace(); message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, ""); new_state(EPOINT_STATE_OUT_DISCONNECT); set_tone(portlist,"activated"); @@ -1257,9 +708,9 @@ void EndpointAppPBX::action_init_change_forward(void) { struct port_list *portlist = ea_endpoint->ep_portlist; - if (!e_ext.change_forward) - { - printlog("%3d action CHANGE-FORWARD denied for this caller.\n", ea_endpoint->ep_serial); + if (!e_ext.change_forward) { + trace_header("ACTION change-forward (denied for this caller)", DIRECTION_NONE); + end_trace(); /* service not available */ message_disconnect_port(portlist, CAUSE_SERVICEUNAVAIL, LOCATION_PRIVATE_LOCAL, ""); new_state(EPOINT_STATE_OUT_DISCONNECT); @@ -1281,43 +732,48 @@ void EndpointAppPBX::action_dialing_forward(void) if ((rparam = routeparam(e_action, PARAM_DIVERSION))) diversion = rparam->integer_value; - if ((rparam = routeparam(e_action, PARAM_DEST))) - { + if ((rparam = routeparam(e_action, PARAM_DEST))) { /* if destination is given */ dest = rparam->string_value; - } else - { + } else { if (!strchr(e_extdialing, '#')) return; *strchr(e_extdialing, '#') = '\0'; dest = e_extdialing; } - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: storing forwarding to '%s'.\n", ea_endpoint->ep_serial, e_terminal, dest); - if (read_extension(&e_ext, e_terminal)) - { - switch(diversion) - { + PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: storing forwarding to '%s'.\n", ea_endpoint->ep_serial, e_ext.number, dest); + if (read_extension(&e_ext, e_ext.number)) { + switch(diversion) { case INFO_DIVERSION_CFU: - printlog("%3d action CHANGE-FORWARD changing CFU (unconditional) to '%s'.\n", ea_endpoint->ep_serial, dest); + trace_header("ACTION change-forward (new CFU=unconditional)", DIRECTION_NONE); + add_trace("destin'", NULL, "%s", dest); + end_trace(); SCPY(e_ext.cfu, dest); break; case INFO_DIVERSION_CFB: - printlog("%3d action CHANGE-FORWARD changing CFB (busy) to '%s'.\n", ea_endpoint->ep_serial, dest); + trace_header("ACTION change-forward (new CFB=busy)", DIRECTION_NONE); + add_trace("destin'", NULL, "%s", dest); + end_trace(); SCPY(e_ext.cfb, dest); break; case INFO_DIVERSION_CFNR: if ((rparam = routeparam(e_action, PARAM_DELAY))) e_ext.cfnr_delay = rparam->integer_value; - printlog("%3d action CHANGE-FORWARD changing CFNR (no response) to '%s' with delay=%d.\n", ea_endpoint->ep_serial, dest, e_ext.cfnr_delay); + trace_header("ACTION change-forward (new CFNR=no response)", DIRECTION_NONE); + add_trace("destin'", NULL, "%s", dest); + add_trace("delay", NULL, "%s", e_ext.cfnr_delay); + end_trace(); SCPY(e_ext.cfnr, dest); break; case INFO_DIVERSION_CFP: - printlog("%3d action CHANGE-FORWARD changing CFP (parallel) to '%s'.\n", ea_endpoint->ep_serial, dest); + trace_header("ACTION change-forward (new CFP=parallel)", DIRECTION_NONE); + add_trace("destin'", NULL, "%s", dest); + end_trace(); SCPY(e_ext.cfp, dest); break; } - write_extension(&e_ext, e_terminal); + write_extension(&e_ext, e_ext.number); } /* function (de)activated */ message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, ""); @@ -1336,10 +792,9 @@ void EndpointAppPBX::action_init_redial_reply(void) struct port_list *portlist = ea_endpoint->ep_portlist; e_select = 0; - if (!e_ext.last_out[0]) - { - printlog("%3d action REDIAL/REPLY no number available to dial.\n", ea_endpoint->ep_serial); - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): no stored last number.\n", ea_endpoint->ep_serial); + if (!e_ext.last_out[0]) { + trace_header("ACTION redial/reply (no last number stored)", DIRECTION_NONE); + end_trace(); new_state(EPOINT_STATE_OUT_DISCONNECT); message_disconnect_port(portlist, CAUSE_SERVICEUNAVAIL, LOCATION_PRIVATE_LOCAL, ""); set_tone(portlist, "cause_3f"); @@ -1351,7 +806,7 @@ void EndpointAppPBX::action_init_redial_reply(void) */ void EndpointAppPBX::_action_redial_reply(int in) { - struct message *message; + struct lcr_msg *message; char *last; struct route_param *rparam; @@ -1368,38 +823,41 @@ void EndpointAppPBX::_action_redial_reply(int in) goto nodisplay; /* scroll menu */ - if (e_extdialing[0]=='*' || e_extdialing[0]=='1') - { + if (e_extdialing[0]=='*' || e_extdialing[0]=='1') { /* find prev entry */ e_select--; if (e_select < 0) e_select = 0; } - if (e_extdialing[0]=='#' || e_extdialing[0]=='3') - { + if (e_extdialing[0]=='#' || e_extdialing[0]=='3') { /* find next entry */ e_select++; - if (e_select >= MAX_REMEMBER) + if (e_select >= MAX_REMEMBER) { e_select--; - else if (in) + } else if (in) { if (e_ext.last_in[e_select][0] == '\0') e_select--; - else + } else if (e_ext.last_out[e_select][0] == '\0') e_select--; } last = (in)?e_ext.last_in[e_select]:e_ext.last_out[e_select]; - if (e_extdialing[0]=='0' || e_extdialing[0]=='2') - { + if (e_extdialing[0]=='0' || e_extdialing[0]=='2') { nodisplay: - printlog("%3d action REDIAL/REPLY dialing '%s'.\n", ea_endpoint->ep_serial, last); - SCPY(e_dialinginfo.number, last); - e_extdialing = e_dialinginfo.number; + if (in) + trace_header("ACTION reply (dialing)", DIRECTION_NONE); + else + trace_header("ACTION redial (dialing)", DIRECTION_NONE); + add_trace("number", NULL, "%s", last); + add_trace("last but", NULL, "%d", e_select); + end_trace(); + SCPY(e_dialinginfo.id, last); + e_extdialing = e_dialinginfo.id; e_action = NULL; - process_dialing(); + process_dialing(0); return; } e_extdialing[0] = '\0'; @@ -1412,9 +870,6 @@ void EndpointAppPBX::_action_redial_reply(int in) if (!strncmp(last, "intern:", 7)) SPRINT(message->param.notifyinfo.display, "(%d) %s int", e_select+1, last+7); else - if (!strncmp(last, "h323:", 5)) - SPRINT(message->param.notifyinfo.display, "(%d) %s h323", e_select+1, last+5); - else if (!strncmp(last, "chan:", 4)) SPRINT(message->param.notifyinfo.display, "(%d) %s chan", e_select+1, last+5); else @@ -1422,9 +877,9 @@ void EndpointAppPBX::_action_redial_reply(int in) SPRINT(message->param.notifyinfo.display, "(%d) %s vbox", e_select+1, last+5); else SPRINT(message->param.notifyinfo.display, "(%d) %s", e_select+1, (last[0])?last:"- empty -"); - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s sending display:%s\n", ea_endpoint->ep_serial, e_terminal, message->param.notifyinfo.display); + PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s sending display:%s\n", ea_endpoint->ep_serial, e_ext.number, message->param.notifyinfo.display); message_put(message); - logmessage(message); + logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT); } /* process dialing redial @@ -1447,14 +902,13 @@ void EndpointAppPBX::action_dialing_reply(void) void EndpointAppPBX::action_dialing_powerdial(void) { struct port_list *portlist = ea_endpoint->ep_portlist; - struct message *message; + struct lcr_msg *message; struct route_param *rparam; /* power dialing only possible if we have a last dialed number */ - if (!e_ext.last_out[0]) - { - printlog("%3d action POWERDIAL no number available to redial.\n", ea_endpoint->ep_serial); - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): no stored last number.\n", ea_endpoint->ep_serial); + if (!e_ext.last_out[0]) { + trace_header("ACTION powerdial (no last number stored)", DIRECTION_NONE); + end_trace(); new_state(EPOINT_STATE_OUT_DISCONNECT); message_disconnect_port(portlist, CAUSE_SERVICEUNAVAIL, LOCATION_PRIVATE_LOCAL, ""); set_tone(portlist, "cause_3f"); @@ -1462,20 +916,16 @@ void EndpointAppPBX::action_dialing_powerdial(void) } /* limit */ - if ((rparam = routeparam(e_action, PARAM_LIMIT))) - { + if ((rparam = routeparam(e_action, PARAM_LIMIT))) { e_powerlimit = rparam->integer_value; - } else - { + } else { e_powerlimit = 0; } /* delay */ - if ((rparam = routeparam(e_action, PARAM_DELAY))) - { + if ((rparam = routeparam(e_action, PARAM_DELAY))) { e_powerdelay = rparam->integer_value; - } else - { + } else { /* delay incomplete */ if (!strchr(e_extdialing, '#')) return; @@ -1485,24 +935,26 @@ void EndpointAppPBX::action_dialing_powerdial(void) if (e_powerdelay < 1) e_powerdelay = 0.2; - printlog("%3d action POWERDIAL to '%s' with delay=%d.\n", ea_endpoint->ep_serial, e_ext.last_out[0], (int)e_powerdelay); - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): powerdialing to '%s' (delay=%d).\n", ea_endpoint->ep_serial, e_ext.last_out[0], (int)e_powerdelay); + trace_header("ACTION powerdial (dialing)", DIRECTION_NONE); + add_trace("number", NULL, "%s", e_ext.last_out[0]); + add_trace("delay", NULL, "%d", e_powerdelay); + end_trace(); /* send connect to avoid overlap timeout */ // new_state(EPOINT_STATE_CONNECT); connect may prevent further dialing - if (e_terminal[0]) + if (e_ext.number[0]) e_dtmf = 1; memset(&e_connectinfo, 0, sizeof(e_connectinfo)); message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT); message_put(message); - logmessage(message); + logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT); /* do dialing */ - SCPY(e_dialinginfo.number, e_ext.last_out[0]); - e_powerdialing = -1; /* indicates the existence of powerdialing but no redial time given */ + SCPY(e_dialinginfo.id, e_ext.last_out[0]); + e_powerdial_on = 1; /* indicates the existence of powerdialing but no redial time given */ e_powercount = 0; e_action = NULL; - process_dialing(); + process_dialing(0); } @@ -1517,12 +969,12 @@ void EndpointAppPBX::action_dialing_callback(void) portlist = ea_endpoint->ep_portlist; /* check given extension */ - if (!(rparam = routeparam(e_action, PARAM_EXTENSION))) - { - printlog("%3d action CALLBACK no extension was specified in routing.conf.\n", ea_endpoint->ep_serial); - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): rejecting callback, because no extension was specified in routing.conf\n", ea_endpoint->ep_serial); - + if (!(rparam = routeparam(e_action, PARAM_EXTENSION))) { + noextension: + trace_header("ACTION callback (no extension defined)", DIRECTION_NONE); + end_trace(); disconnect: + new_state(EPOINT_STATE_OUT_DISCONNECT); message_disconnect_port(portlist, CAUSE_SERVICEUNAVAIL, LOCATION_PRIVATE_LOCAL, ""); set_tone(portlist, "cause_3f"); @@ -1534,44 +986,41 @@ void EndpointAppPBX::action_dialing_callback(void) /* if extension is given */ SCPY(e_cbcaller, rparam->string_value); if (e_cbcaller[0] == '\0') - { - printlog("%3d action CALLBACK extension specified in routing.conf is an empty string.\n", ea_endpoint->ep_serial); - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): rejecting callback, because given extension is an empty string.\n", ea_endpoint->ep_serial); - goto disconnect; - } + goto noextension; /* read callback extension */ memset(&cbext, 0, sizeof(cbext)); - if (!read_extension(&cbext, e_cbcaller)) - { - printlog("%3d action CALLBACK extension '%s' specified in routing.conf doesn't exist.\n", ea_endpoint->ep_serial, e_cbcaller); - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): rejecting callback, because given extension does not exist.\n", ea_endpoint->ep_serial); + if (!read_extension(&cbext, e_cbcaller)) { + trace_header("ACTION callback (extension doesn't exist)", DIRECTION_NONE); + add_trace("extension", NULL, "%s", e_cbcaller); + end_trace(); goto disconnect; } /* if password is not given */ - if (cbext.password[0] == '\0') - { - printlog("%3d action CALLBACK extension '%s' has no password specified.\n", ea_endpoint->ep_serial, e_cbcaller); - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): rejecting callback, because no password is available in given extension (%s).\n", ea_endpoint->ep_serial, e_cbcaller); + if (cbext.password[0] == '\0') { + trace_header("ACTION callback (no password set)", DIRECTION_NONE); + add_trace("extension", NULL, "%s", e_cbcaller); + end_trace(); goto disconnect; } /* callback only possible if callerid exists OR it is given */ if ((rparam = routeparam(e_action, PARAM_CALLTO))) SCPY(e_cbto, rparam->string_value); - if (e_cbto[0]) - { - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): callback to given number: '%s'\n", ea_endpoint->ep_serial, e_cbto); - printlog("%3d action CALLBACK callback to given number: '%s'\n", ea_endpoint->ep_serial, e_cbto); + if (e_cbto[0]) { + trace_header("ACTION callback (alternative caller id)", DIRECTION_NONE); + add_trace("extension", NULL, "%s", e_cbcaller); + add_trace("callerid", NULL, "%s", e_cbto); + end_trace(); SCPY(e_callerinfo.id, e_cbto); e_callerinfo.ntype = INFO_NTYPE_UNKNOWN; e_callerinfo.present = INFO_PRESENT_ALLOWED; } - if (e_callerinfo.id[0]=='\0' || e_callerinfo.present==INFO_PRESENT_NOTAVAIL) - { - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): rejecting callback, because no caller id is available\n", ea_endpoint->ep_serial); - printlog("%3d action CALLBACK not possible because caller ID is not available.\n", ea_endpoint->ep_serial); + if (e_callerinfo.id[0]=='\0' || e_callerinfo.present==INFO_PRESENT_NOTAVAIL) { + trace_header("ACTION callback (no caller ID available)", DIRECTION_NONE); + add_trace("extension", NULL, "%s", e_cbcaller); + end_trace(); goto disconnect; } /* present id */ @@ -1599,11 +1048,15 @@ void EndpointAppPBX::action_hangup_callback(void) else SCPY(e_cbdialing, e_extdialing); - printlog("%3d action CALLBACK extension=%s callerid='%s' delay='%d' dialing after callback='%s' .\n", ea_endpoint->ep_serial, e_cbcaller, e_callerinfo.id, delay, e_cbdialing); - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): caller '%s', callerid '%s', dialing '%s', delay %d\n", ea_endpoint->ep_serial, e_cbcaller, e_callerinfo.id, e_cbdialing, delay); + trace_header("ACTION callback (dialing)", DIRECTION_NONE); + add_trace("extension", NULL, "%s", e_cbcaller); + add_trace("caller id", NULL, "%s", e_callerinfo.id); + add_trace("delay", NULL, "%d", delay); + add_trace("dialing", NULL, "%s", e_cbdialing); + end_trace(); /* set time to callback */ - e_callback = now_d + delay; + schedule_timer(&e_callback_timeout, delay, 0); } @@ -1619,9 +1072,9 @@ void EndpointAppPBX::action_dialing_abbrev(void) portlist = ea_endpoint->ep_portlist; /* abbrev dialing is only possible if we have a caller defined */ - if (!e_terminal[0]) - { - printlog("%3d action ABBREVIATION only possible for internal callers.\n", ea_endpoint->ep_serial); + if (!e_ext.number[0]) { + trace_header("ACTION abbreviation (only for extension)", DIRECTION_NONE); + end_trace(); new_state(EPOINT_STATE_OUT_DISCONNECT); message_disconnect_port(portlist, CAUSE_SERVICEUNAVAIL, LOCATION_PRIVATE_LOCAL, ""); set_tone(portlist, "cause_3f"); @@ -1632,26 +1085,31 @@ void EndpointAppPBX::action_dialing_abbrev(void) abbrev = e_extdialing; phone = NULL; name = NULL; - result = parse_phonebook(e_terminal, &abbrev, &phone, &name); - if (result == 0) - { - printlog("%3d action ABBREVIATION '%s' not found.\n", ea_endpoint->ep_serial, abbrev); + result = parse_phonebook(e_ext.number, &abbrev, &phone, &name); + if (result == 0) { + trace_header("ACTION abbreviation (not found)", DIRECTION_NONE); + add_trace("abbrev", NULL, "%s", abbrev); + end_trace(); new_state(EPOINT_STATE_OUT_DISCONNECT); message_disconnect_port(portlist, CAUSE_UNALLOCATED, LOCATION_PRIVATE_LOCAL, ""); set_tone(portlist, "cause_01"); return; } - if (result == -1) /* may match if more digits are dialed */ - { + if (result == -1) { /* may match if more digits are dialed */ return; } /* dial abbreviation */ - printlog("%3d action ABBREVIATION mapping '%s' to '%s' (%s), dialing...\n", ea_endpoint->ep_serial, abbrev, phone, name?name:"unknown"); - SCPY(e_dialinginfo.number, phone); - e_extdialing = e_dialinginfo.number; + trace_header("ACTION abbreviation (dialing)", DIRECTION_NONE); + add_trace("abbrev", NULL, "%s", abbrev); + add_trace("number", NULL, "%s", phone); + if (name) if (name[0]) + add_trace("name", NULL, "%s", name); + end_trace(); + SCPY(e_dialinginfo.id, phone); + e_extdialing = e_dialinginfo.id; e_action = NULL; - process_dialing(); + process_dialing(0); } @@ -1662,7 +1120,7 @@ void EndpointAppPBX::action_dialing_test(void) unsigned int cause; char causestr[16]; struct port_list *portlist = ea_endpoint->ep_portlist; - struct message *message; + struct lcr_msg *message; class Port *port; char testcode[32] = ""; struct route_param *rparam; @@ -1672,36 +1130,40 @@ void EndpointAppPBX::action_dialing_test(void) SCPY(testcode, rparam->string_value); SCAT(testcode, e_extdialing); - switch(testcode[0]) - { + switch(testcode[0]) { case '1': - printlog("%3d action TESTMODE executing 'proceeding' test.\n", ea_endpoint->ep_serial); + trace_header("ACTION test", DIRECTION_NONE); + add_trace("test", NULL, "proceeding"); + end_trace(); new_state(EPOINT_STATE_IN_PROCEEDING); set_tone(portlist, "proceeding"); message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING); message_put(message); - logmessage(message); + logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT); break; case '2': - printlog("%3d action TESTMODE executing 'alerting' test.\n", ea_endpoint->ep_serial); + trace_header("ACTION test", DIRECTION_NONE); + add_trace("test", NULL, "alerting"); + end_trace(); new_state(EPOINT_STATE_IN_ALERTING); set_tone(portlist, "ringpbx"); message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING); message_put(message); - logmessage(message); + logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT); break; case '3': - printlog("%3d action TESTMODE executing 'echo connect' test.\n", ea_endpoint->ep_serial); + trace_header("ACTION test", DIRECTION_NONE); + add_trace("test", NULL, "echo"); + end_trace(); new_state(EPOINT_STATE_CONNECT); - if (e_terminal[0]) + if (e_ext.number[0]) e_dtmf = 1; set_tone(portlist, NULL); memset(&e_connectinfo, 0, sizeof(e_connectinfo)); SCPY(e_connectinfo.id, e_callerinfo.id); - SCPY(e_connectinfo.intern, e_callerinfo.intern); - SCPY(e_connectinfo.voip, e_callerinfo.voip); + SCPY(e_connectinfo.extension, e_callerinfo.extension); e_connectinfo.itype = e_callerinfo.itype; e_connectinfo.ntype = e_callerinfo.ntype; e_connectinfo.present = e_callerinfo.present; @@ -1709,40 +1171,43 @@ void EndpointAppPBX::action_dialing_test(void) message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT); memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info)); /* handle restricted caller ids */ - apply_callerid_restriction(e_ext.anon_ignore, portlist->port_type, message->param.connectinfo.id, &message->param.connectinfo.ntype, &message->param.connectinfo.present, &message->param.connectinfo.screen, message->param.connectinfo.voip, message->param.connectinfo.intern, message->param.connectinfo.name); + apply_callerid_restriction(&e_ext, message->param.connectinfo.id, &message->param.connectinfo.ntype, &message->param.connectinfo.present, &message->param.connectinfo.screen, message->param.connectinfo.extension, message->param.connectinfo.name); /* display callerid if desired for extension */ - SCPY(message->param.connectinfo.display, apply_callerid_display(message->param.connectinfo.id, message->param.connectinfo.itype, message->param.connectinfo.ntype, message->param.connectinfo.present, message->param.connectinfo.screen, message->param.connectinfo.voip, message->param.connectinfo.intern, message->param.connectinfo.name)); + 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)); message_put(message); - logmessage(message); + logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT); port = find_port_id(portlist->port_id); - if (port) - { + if (port) { port->set_echotest(1); } break; case '4': - printlog("%3d action TESTMODE executing 'tone connect' test.\n", ea_endpoint->ep_serial); + trace_header("ACTION test", DIRECTION_NONE); + add_trace("test", NULL, "tone"); + end_trace(); new_state(EPOINT_STATE_CONNECT); - if (e_terminal[0]) + if (e_ext.number[0]) e_dtmf = 1; memset(&e_connectinfo, 0, sizeof(e_connectinfo)); message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT); message_put(message); - logmessage(message); + logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT); set_tone(portlist, "test"); break; case '5': - printlog("%3d action TESTMODE executing 'hold music' test.\n", ea_endpoint->ep_serial); + trace_header("ACTION test", DIRECTION_NONE); + add_trace("test", NULL, "hold music"); + end_trace(); new_state(EPOINT_STATE_CONNECT); - if (e_terminal[0]) + if (e_ext.number[0]) e_dtmf = 1; memset(&e_connectinfo, 0, sizeof(e_connectinfo)); message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT); message_put(message); - logmessage(message); + logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT); set_tone(portlist, "hold"); break; @@ -1753,15 +1218,18 @@ void EndpointAppPBX::action_dialing_test(void) cause = atoi(testcode+1); if (cause > 255) cause = 0; - printlog("%3d action TESTMODE executing 'announcement' test with cause %d.\n", ea_endpoint->ep_serial, cause); + trace_header("ACTION test", DIRECTION_NONE); + add_trace("test", NULL, "announcement"); + add_trace("cause", NULL, "%d", cause); + end_trace(); new_state(EPOINT_STATE_CONNECT); - if (e_terminal[0]) + if (e_ext.number[0]) e_dtmf = 1; SPRINT(causestr,"cause_%02x",cause); memset(&e_connectinfo, 0, sizeof(e_connectinfo)); message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT); message_put(message); - logmessage(message); + logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT); set_tone(portlist, causestr); break; @@ -1772,7 +1240,10 @@ void EndpointAppPBX::action_dialing_test(void) cause = atoi(testcode+1); if (cause > 127) cause = 0; - printlog("%3d action TESTMODE executing 'disconnect' test with cause %d.\n", ea_endpoint->ep_serial, cause); + trace_header("ACTION test", DIRECTION_NONE); + add_trace("test", NULL, "disconnect"); + add_trace("cause", NULL, "%d", cause); + end_trace(); new_state(EPOINT_STATE_OUT_DISCONNECT); SPRINT(causestr,"cause_%02x",cause); message_disconnect_port(portlist, cause, LOCATION_PRIVATE_LOCAL, ""); @@ -1780,27 +1251,32 @@ void EndpointAppPBX::action_dialing_test(void) break; case '8': /* release */ - printlog("%3d action TESTMODE executing 'release' test.\n", ea_endpoint->ep_serial); + trace_header("ACTION test", DIRECTION_NONE); + add_trace("test", NULL, "release"); + add_trace("cause", NULL, "16"); + end_trace(); new_state(EPOINT_STATE_OUT_DISCONNECT); message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, ""); set_tone(portlist, "release"); break; case '9': /* text callerid test */ - printlog("%3d action TESTMODE executing 'caller id' test.\n", ea_endpoint->ep_serial); + trace_header("ACTION test", DIRECTION_NONE); + add_trace("test", NULL, "callerid"); + end_trace(); new_state(EPOINT_STATE_CONNECT); - if (e_terminal[0]) + if (e_ext.number[0]) e_dtmf = 1; memset(&e_connectinfo, 0, sizeof(e_connectinfo)); SCPY(e_connectinfo.id, "12345678"); - SCPY(e_connectinfo.name, "Welcome to Linux"); - SCPY(e_connectinfo.display, "Welcome to Linux"); + SCPY(e_connectinfo.name, "Welcome to LCR"); + SCPY(e_connectinfo.display, "Welcome to LCR"); e_connectinfo.ntype = INFO_NTYPE_UNKNOWN; e_connectinfo.present = INFO_PRESENT_ALLOWED; message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT); memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(message->param.connectinfo)); message_put(message); - logmessage(message); + logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT); set_tone(portlist, "hold"); break; } @@ -1815,10 +1291,9 @@ void EndpointAppPBX::action_init_play(void) struct port_list *portlist = ea_endpoint->ep_portlist; /* check given sample */ - if (!(rparam = routeparam(e_action, PARAM_SAMPLE))) - { - printlog("%3d action PLAY no sample given.\n", ea_endpoint->ep_serial); - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): cannot play, because no sample has been specified\n", ea_endpoint->ep_serial); + if (!(rparam = routeparam(e_action, PARAM_SAMPLE))) { + trace_header("ACTION play (no sample given)", DIRECTION_NONE); + end_trace(); disconnect: new_state(EPOINT_STATE_OUT_DISCONNECT); @@ -1829,14 +1304,13 @@ void EndpointAppPBX::action_init_play(void) } /* if sample is given */ - if (rparam->string_value[0] == '\0') - { - printlog("%3d action PLAY sample name with empty string given.\n", ea_endpoint->ep_serial); - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): cannot play, because given sample is an empty string.\n", ea_endpoint->ep_serial); + if (rparam->string_value[0] == '\0') { + trace_header("ACTION play (no sample given)", DIRECTION_NONE); + end_trace(); goto disconnect; } - if (e_terminal[0]) + if (e_ext.number[0]) e_dtmf = 1; set_tone(ea_endpoint->ep_portlist, rparam->string_value); @@ -1854,24 +1328,21 @@ void EndpointAppPBX::action_init_play(void) void EndpointAppPBX::action_dialing_calculator(void) { struct port_list *portlist = ea_endpoint->ep_portlist; - struct message *message; + struct lcr_msg *message; double value1, value2, v, sign1; - int komma1, komma2, k, state, mode, first; + int komma1, komma2, k, state, mode = 0, first; char *p; portlist = ea_endpoint->ep_portlist; /* remove error message */ - if (!strncmp(e_extdialing, "Error", 5)) - { + if (!strncmp(e_extdialing, "Error", 5)) { UCPY(e_extdialing, e_extdialing+5); } - if (!strncmp(e_extdialing, "inf", 3)) - { + if (!strncmp(e_extdialing, "inf", 3)) { UCPY(e_extdialing, e_extdialing+3); } - if (!strncmp(e_extdialing, "-inf", 4)) - { + if (!strncmp(e_extdialing, "-inf", 4)) { UCPY(e_extdialing, e_extdialing+4); } @@ -1886,31 +1357,24 @@ void EndpointAppPBX::action_dialing_calculator(void) if (!p) return; first = 1; - while(*p) - { - if (*p>='0' && *p<='9') - { + while(*p) { + if (*p>='0' && *p<='9') { #if 0 - if (first) - { + if (first) { UCPY(p, p+1); continue; } - if ((p[-1]<'0' || p[-1]>'0') && p[-1]!='.') - { + if ((p[-1]<'0' || p[-1]>'0') && p[-1]!='.') { p--; UCPY(p, p+1); continue; } #endif - switch(state) - { + switch(state) { case 0: /* first number */ - if (!komma1) - { + if (!komma1) { value1 = value1*10 + (*p-'0'); - } else - { + } else { k = komma1++; v = *p-'0'; while(k--) @@ -1919,11 +1383,9 @@ void EndpointAppPBX::action_dialing_calculator(void) } break; case 1: /* second number */ - if (!komma2) - { + if (!komma2) { value2 = value2*10 + (*p-'0'); - } else - { + } else { k = komma2++; v = *p-'0'; while(k--) @@ -1933,17 +1395,14 @@ void EndpointAppPBX::action_dialing_calculator(void) break; } } else - switch(*p) - { + switch(*p) { case '*': - if (first) - { + if (first) { UCPY(e_extdialing, "Error"); goto done; } /* if there is a multiplication, we change to / */ - if (p[-1] == '*') - { + if (p[-1] == '*') { mode = 1; p[-1] = '/'; UCPY(p, p+1); @@ -1951,8 +1410,7 @@ void EndpointAppPBX::action_dialing_calculator(void) break; } /* if there is a division, we change to + */ - if (p[-1] == '/') - { + if (p[-1] == '/') { mode = 2; p[-1] = '+'; UCPY(p, p+1); @@ -1960,8 +1418,7 @@ void EndpointAppPBX::action_dialing_calculator(void) break; } /* if there is a addition, we change to - */ - if (p[-1] == '+') - { + if (p[-1] == '+') { mode = 3; p[-1] = '-'; UCPY(p, p+1); @@ -1969,8 +1426,7 @@ void EndpointAppPBX::action_dialing_calculator(void) break; } /* if there is a substraction and a comma, we change to * */ - if (p[-1]=='-' && komma1) - { + if (p[-1]=='-' && komma1) { mode = 0; p[-1] = '*'; UCPY(p, p+1); @@ -1978,8 +1434,7 @@ void EndpointAppPBX::action_dialing_calculator(void) break; } /* if there is a substraction and no comma and the first or second value, we change to , */ - if (p[-1]=='-') - { + if (p[-1]=='-') { p[-1] = '.'; UCPY(p, p+1); p--; @@ -1987,8 +1442,7 @@ void EndpointAppPBX::action_dialing_calculator(void) break; } /* if there is a komma and we are at the first value, we change to * */ - if (p[-1]=='.' && state==0) - { + if (p[-1]=='.' && state==0) { mode = 0; p[-1] = '*'; UCPY(p, p+1); @@ -1997,14 +1451,12 @@ void EndpointAppPBX::action_dialing_calculator(void) break; } /* if there is a komma and we are at the second value, we display error */ - if (komma2 && state==1) - { + if (komma2 && state==1) { UCPY(e_extdialing, "Error"); goto done; } /* if we are at state 1, we write a comma */ - if (state == 1) - { + if (state == 1) { *p = '.'; komma2 = 1; break; @@ -2017,30 +1469,27 @@ void EndpointAppPBX::action_dialing_calculator(void) case '#': /* if just a number is displayed, the input is cleared */ - if (state==0) - { + if (state==0) { *e_extdialing = '\0'; break; } /* calculate the result */ - switch(mode) - { + switch(mode) { case 0: /* multiply */ - UNPRINT(e_extdialing, sizeof(e_dialinginfo.number)-strlen(e_dialinginfo.number), "%.8f", sign1*value1*value2); + UNPRINT(e_extdialing, sizeof(e_dialinginfo.id)-strlen(e_dialinginfo.id), "%.8f", sign1*value1*value2); break; case 1: /* divide */ - UNPRINT(e_extdialing, sizeof(e_dialinginfo.number)-strlen(e_dialinginfo.number), "%.8f", sign1*value1/value2); + UNPRINT(e_extdialing, sizeof(e_dialinginfo.id)-strlen(e_dialinginfo.id), "%.8f", sign1*value1/value2); break; case 2: /* add */ - UNPRINT(e_extdialing, sizeof(e_dialinginfo.number)-strlen(e_dialinginfo.number), "%.8f", sign1*value1+value2); + UNPRINT(e_extdialing, sizeof(e_dialinginfo.id)-strlen(e_dialinginfo.id), "%.8f", sign1*value1+value2); break; case 3: /* substract */ - UNPRINT(e_extdialing, sizeof(e_dialinginfo.number)-strlen(e_dialinginfo.number), "%.8f", sign1*value1-value2); + UNPRINT(e_extdialing, sizeof(e_dialinginfo.id)-strlen(e_dialinginfo.id), "%.8f", sign1*value1-value2); break; } - e_dialinginfo.number[sizeof(e_dialinginfo.number)-1] = '\0'; - if (strchr(e_extdialing, '.')) /* remove zeroes */ - { + e_dialinginfo.id[sizeof(e_dialinginfo.id)-1] = '\0'; + if (strchr(e_extdialing, '.')) { /* remove zeroes */ while (e_extdialing[strlen(e_extdialing)-1] == '0') e_extdialing[strlen(e_extdialing)-1] = '\0'; if (e_extdialing[strlen(e_extdialing)-1] == '.') @@ -2068,8 +1517,7 @@ void EndpointAppPBX::action_dialing_calculator(void) break; case '-': - if (first) - { + if (first) { sign1=-1; break; } @@ -2091,9 +1539,9 @@ void EndpointAppPBX::action_dialing_calculator(void) /* display dialing */ message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY); SPRINT(message->param.notifyinfo.display, ">%s", e_extdialing); - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s displaying interpreted dialing '%s' internal values: %f %f\n", ea_endpoint->ep_serial, e_terminal, e_extdialing, value1, value2); + PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s displaying interpreted dialing '%s' internal values: %f %f\n", ea_endpoint->ep_serial, e_ext.number, e_extdialing, value1, value2); message_put(message); - logmessage(message); + logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT); } @@ -2114,11 +1562,10 @@ void EndpointAppPBX::_action_goto_menu(int mode) struct route_param *rparam; /* check given ruleset */ - if (!(rparam = routeparam(e_action, PARAM_RULESET))) - { + if (!(rparam = routeparam(e_action, PARAM_RULESET))) { no_ruleset: - printlog("%3d action GOTO/MENU no ruleset ginven in options.conf\n", ea_endpoint->ep_serial); - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): no ruleset was secified for action '%s' in routing.conf\n", ea_endpoint->ep_serial, (mode)?"menu":"goto"); + trace_header("ACTION goto/menu (no ruleset given)", DIRECTION_NONE); + end_trace(); disconnect: new_state(EPOINT_STATE_OUT_DISCONNECT); @@ -2130,35 +1577,44 @@ void EndpointAppPBX::_action_goto_menu(int mode) if (rparam->string_value[0] == '\0') goto no_ruleset; e_ruleset = getrulesetbyname(rparam->string_value); - if (!e_ruleset) - { - printlog("%3d action GOTO/MENU given ruleset '%s' not found in options.conf\n", ea_endpoint->ep_serial, rparam->string_value); - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): given ruleset '%s' for action '%s' was not found in routing.conf\n", ea_endpoint->ep_serial, rparam->string_value, (mode)?"menu":"goto"); + if (!e_ruleset) { + trace_header("ACTION goto/menu (ruleset not found)", DIRECTION_NONE); + add_trace("ruleset", NULL, "%s", rparam->string_value); + end_trace(); goto disconnect; } - printlog("%3d action GOTO/MENU changing to ruleset '%s'\n", ea_endpoint->ep_serial, rparam->string_value); /* if the 'menu' was selected, we will flush all digits */ - if (mode) - { - //SCPY(e_dialinginfo.number, e_extdialing); - e_dialinginfo.number[0] = 0; - e_extdialing = e_dialinginfo.number; - } else - { + if (mode) { + e_dialinginfo.id[0] = 0; + e_dialinginfo.sending_complete = 0; + e_extdialing = e_dialinginfo.id; + } else { + /* remove digits that are required to match the rule */ + if ((rparam = routeparam(e_action, PARAM_STRIP))) { + if (e_extdialing) + SCPY(e_dialinginfo.id, e_extdialing); + e_extdialing = e_dialinginfo.id; + } } /* play sample */ - if ((rparam = routeparam(e_action, PARAM_SAMPLE))) - { - printlog("%3d action GOTO/MENU start playing sample '%s'\n", ea_endpoint->ep_serial, rparam->string_value); - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): playing sample '%s'\n", ea_endpoint->ep_serial, rparam->string_value); + trace_header("ACTION goto/menu (change to)", DIRECTION_NONE); + add_trace("ruleset", NULL, "%s", e_ruleset->name); + if (e_dialinginfo.id[0]) { + add_trace("dialing", NULL, "%s", e_dialinginfo.id); + } + if ((rparam = routeparam(e_action, PARAM_SAMPLE))) { + add_trace("sample", NULL, "%s", rparam->string_value); + end_trace(); set_tone(ea_endpoint->ep_portlist, rparam->string_value); + } else { + end_trace(); } /* do dialing with new ruleset */ e_action = NULL; - process_dialing(); + process_dialing(0); } /* process dialing goto @@ -2183,19 +1639,17 @@ void EndpointAppPBX::action_dialing_disconnect(void) { struct route_param *rparam; struct port_list *portlist = ea_endpoint->ep_portlist; - struct message *message; + struct lcr_msg *message; int cause = CAUSE_NORMAL; /* normal call clearing */ int location = LOCATION_PRIVATE_LOCAL; char cause_string[256] = "", display[84] = ""; /* check cause parameter */ - if ((rparam = routeparam(e_action, PARAM_CAUSE))) - { + if ((rparam = routeparam(e_action, PARAM_CAUSE))) { cause = rparam->integer_value; PDEBUG(DEBUG_EPOINT, "EPOINT(%d): 'cause' is given: %d\n", ea_endpoint->ep_serial, cause); } - if ((rparam = routeparam(e_action, PARAM_LOCATION))) - { + if ((rparam = routeparam(e_action, PARAM_LOCATION))) { location = rparam->integer_value; PDEBUG(DEBUG_EPOINT, "EPOINT(%d): 'location' is given: %d\n", ea_endpoint->ep_serial, location); } @@ -2205,38 +1659,83 @@ void EndpointAppPBX::action_dialing_disconnect(void) SPRINT(cause_string, "cause_%02x", cause); /* check sample parameter */ - if ((rparam = routeparam(e_action, PARAM_SAMPLE))) - { + if ((rparam = routeparam(e_action, PARAM_SAMPLE))) { SCPY(cause_string, rparam->string_value); PDEBUG(DEBUG_EPOINT, "EPOINT(%d): 'sample' is given: %s\n", ea_endpoint->ep_serial, cause_string); } /* check display */ - if ((rparam = routeparam(e_action, PARAM_DISPLAY))) - { + if ((rparam = routeparam(e_action, PARAM_DISPLAY))) { SCPY(display, rparam->string_value); PDEBUG(DEBUG_EPOINT, "EPOINT(%d): 'display' is given: %s\n", ea_endpoint->ep_serial, display); } /* disconnect only if connect parameter is not given */ - printlog("%3d action DISCONNECT with cause %d, location %d, sample '%s', display '%s'\n", ea_endpoint->ep_serial, cause, location, cause_string, display); + trace_header("ACTION disconnect", DIRECTION_NONE); + add_trace("cause", "value", "%d", cause); + add_trace("cause", "location", "%d", location); + if (cause_string[0]) + add_trace("sample", NULL, "%s", cause_string); + if (display[0]) + add_trace("display", NULL, "%s", display); + end_trace(); new_state(EPOINT_STATE_OUT_DISCONNECT); set_tone(portlist, cause_string); - if (!(rparam = routeparam(e_action, PARAM_CONNECT))) - { + if (!(rparam = routeparam(e_action, PARAM_CONNECT))) { message_disconnect_port(portlist, cause, location, display); - } else - { + } else { message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY); SCPY(message->param.notifyinfo.display, display); message_put(message); - logmessage(message); + logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT); } e_action = NULL; } /* + * process dialing release + */ +void EndpointAppPBX::action_dialing_release(void) +{ + struct route_param *rparam; + int cause = CAUSE_NORMAL; /* normal call clearing */ + int location = LOCATION_PRIVATE_LOCAL; + char cause_string[256] = "", display[84] = ""; + + /* check cause parameter */ + if ((rparam = routeparam(e_action, PARAM_CAUSE))) { + cause = rparam->integer_value; + PDEBUG(DEBUG_EPOINT, "EPOINT(%d): 'cause' is given: %d\n", ea_endpoint->ep_serial, cause); + } + if ((rparam = routeparam(e_action, PARAM_LOCATION))) { + location = rparam->integer_value; + PDEBUG(DEBUG_EPOINT, "EPOINT(%d): 'location' is given: %d\n", ea_endpoint->ep_serial, location); + } + + + /* use cause as sample, if not given later */ + SPRINT(cause_string, "cause_%02x", cause); + + /* check display */ + if ((rparam = routeparam(e_action, PARAM_DISPLAY))) { + SCPY(display, rparam->string_value); + PDEBUG(DEBUG_EPOINT, "EPOINT(%d): 'display' is given: %s\n", ea_endpoint->ep_serial, display); + } + + /* disconnect only if connect parameter is not given */ + trace_header("ACTION release", DIRECTION_NONE); + add_trace("cause", "value", "%d", cause); + add_trace("cause", "location", "%d", location); + if (display[0]) + add_trace("display", NULL, "%s", display); + end_trace(); + e_action = NULL; + release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, location, cause, 1); + return; +} + +/* * process dialing help */ void EndpointAppPBX::action_dialing_help(void) @@ -2244,9 +1743,9 @@ void EndpointAppPBX::action_dialing_help(void) /* show all things that would match */ #if 0 struct numbering *numbering = numbering_int; - char dialing[sizeof(e_dialinginfo.number)]; + char dialing[sizeof(e_dialinginfo.id)]; int i; - struct message *message; + struct lcr_msg *message; struct route_param *rparam; /* in case we have no menu (this should never happen) */ @@ -2254,36 +1753,29 @@ void EndpointAppPBX::action_dialing_help(void) return; /* scroll menu */ - if (strchr(e_dialinginfo.number,'*')) - { + if (strchr(e_dialinginfo.id,'*')) { e_menu--; - e_dialinginfo.number[0] = '\0'; + e_dialinginfo.id[0] = '\0'; } - if (strchr(e_dialinginfo.number,'#')) - { + if (strchr(e_dialinginfo.id,'#')) { e_menu++; - e_dialinginfo.number[0] = '\0'; + e_dialinginfo.id[0] = '\0'; } /* get position in menu */ - if (e_menu < 0) - { + if (e_menu < 0) { /* get last menu position */ e_menu = 0; - while(numbering->next) - { + while(numbering->next) { e_menu++; numbering = numbering->next; } - } else - { + } else { /* get menu position */ i = 0; - while(i < e_menu) - { + while(i < e_menu) { numbering = numbering->next; - if (!numbering) - { + if (!numbering) { e_menu = 0; numbering = numbering_int; break; @@ -2293,26 +1785,25 @@ void EndpointAppPBX::action_dialing_help(void) } /* if we dial something else we need to add the prefix and change the action */ - if (e_dialinginfo.number[0]) - { + if (e_dialinginfo.id[0]) { e_action = NUMB_ACTION_NONE; SCPY(dialing, numbering->prefix); //we ignore the first digit after selecting - //SCAT(dialing, e_dialinginfo.number); - SCPY(e_dialinginfo.number, dialing); - e_extdialing = e_dialinginfo.number+strlen(numbering->prefix); - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s selected a new menu '%s' dialing: %s\n", ea_endpoint->ep_serial, e_terminal, numb_actions[numbering->action], e_dialinginfo.number); + //SCAT(dialing, e_dialinginfo.id); + SCPY(e_dialinginfo.id, dialing); + e_extdialing = e_dialinginfo.id+strlen(numbering->prefix); + PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s selected a new menu '%s' dialing: %s\n", ea_endpoint->ep_serial, e_ext.number, numb_actions[numbering->action], e_dialinginfo.id); nesting?: - process_dialing(); + process_dialing(0); return; } /* send display message to port */ message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY); SPRINT(message->param.notifyinfo.display, ">%s %s%s%s", numbering->prefix, numb_actions[numbering->action], (numbering->param[0])?" ":"", numbering->param); - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s selected a new menu '%s' sending display:%s\n", ea_endpoint->ep_serial, e_terminal, numb_actions[numbering->action], message->param.notifyinfo.display); + PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s selected a new menu '%s' sending display:%s\n", ea_endpoint->ep_serial, e_ext.number, numb_actions[numbering->action], message->param.notifyinfo.display); message_put(message); - logmessage(message); + logmessage(message->type, message->paramea_endpoint->ep_portlist->port_id, DIRECTION_OUT); #endif } @@ -2332,46 +1823,107 @@ void EndpointAppPBX::action_dialing_setforward(void) { } +/* + * process init 'execute' + */ +void EndpointAppPBX::action_init_execute(void) +{ + struct route_param *rparam; + int executeon = INFO_ON_HANGUP; /* Use Hangup as a default for compatibility */ + + /* Get the execute on parameter */ + if ((rparam = routeparam(e_action, PARAM_ON))) + executeon = rparam->integer_value; + + /* Execute this action if init was specified */ + if (executeon == INFO_ON_INIT) { + trace_header("ACTION execute ON init", DIRECTION_NONE); + end_trace(); + action_execute(); + } +} /* * process hangup 'execute' - */ + */ void EndpointAppPBX::action_hangup_execute(void) { struct route_param *rparam; - char *command = "", isdn_port[10]; - char *argv[8+1]; /* check also number of args below */ + int executeon = INFO_ON_HANGUP; /* Use Hangup as a default for compatibility */ + + /* Get the execute on parameter */ + if ((rparam = routeparam(e_action, PARAM_ON))) + executeon = rparam->integer_value; + + /* Execute this action if init was specified */ + if (executeon == INFO_ON_HANGUP) { + trace_header("ACTION execute ON hangup", DIRECTION_NONE); + end_trace(); + action_execute(); + } +} + +/* + * process 'execute' from action_init_execute or action_hangup_execute + */ +void EndpointAppPBX::action_execute(void) +{ + struct route_param *rparam; + pid_t pid; + pid_t pid2; + int iWaitStatus; + char *command = (char *)""; + char isdn_port[10]; + char *argv[12]; /* check also number of args below */ int i = 0; /* get script / command */ if ((rparam = routeparam(e_action, PARAM_EXECUTE))) command = rparam->string_value; - if (command[0] == '\0') - { - printlog("%3d action EXECUTE no 'execute' parameter given at routing.conf.\n", ea_endpoint->ep_serial); - PERROR("EPOINT(%d): terminal %s: NO PARAMETER GIVEN for 'execute' action. see routing.conf\n", ea_endpoint->ep_serial, e_terminal); + if (command[0] == '\0') { + trace_header("ACTION execute (no parameter given)", DIRECTION_NONE); + end_trace(); return; } - printlog("%3d action EXECUTE command='%s'\n", ea_endpoint->ep_serial, command); - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: executing '%s'.\n", ea_endpoint->ep_serial, e_terminal, command); - - argv[0] = command; - while(strchr(argv[0], '/')) - argv[0] = strchr(argv[0], '/')+1; - if ((rparam = routeparam(e_action, PARAM_PARAM))) - { - argv[1] = rparam->string_value; - i++; - } - argv[1+i] = e_extdialing; - argv[2+i] = numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype); - argv[3+i] = e_callerinfo.intern; - argv[4+i] = e_callerinfo.voip; - argv[5+i] = e_callerinfo.name; +#if 0 + argv[i++] = (char *)"/bin/sh"; + argv[i++] = (char *)"-c"; + argv[i++] = command; +#endif + argv[i++] = command; + if ((rparam = routeparam(e_action, PARAM_PARAM))) { + argv[i++] = rparam->string_value; + } + argv[i++] = e_extdialing; + argv[i++] = (char *)numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype, options.national, options.international); + argv[i++] = e_callerinfo.extension; + argv[i++] = e_callerinfo.name; SPRINT(isdn_port, "%d", e_callerinfo.isdn_port); - argv[6+i] = isdn_port; - argv[7+i] = NULL; /* check also number of args above */ - execve("/bin/sh", argv, environ); + argv[i++] = isdn_port; + argv[i++] = e_callerinfo.imsi; + argv[i++] = NULL; /* check also number of args above */ + switch (pid = fork ()) { + case -1: + trace_header("ACTION execute (fork failed)", DIRECTION_NONE); + end_trace(); + break; + case 0: + /* To be shure there are no zombies created double fork */ + if ((pid2 = fork()) == 0) { + execve(command, argv, environ); + } + /* Exit immediately and release the waiting parent. The subprocess falls to init because the parent died */ + exit(0); + break; + default: + trace_header("ACTION execute", DIRECTION_NONE); + add_trace("command", NULL, "%s", command); + end_trace(); + + /* Wait for the pid. The forked process will exit immediately so there is no problem waiting. */ + waitpid(pid, &iWaitStatus, 0); + break; + } } @@ -2381,7 +1933,7 @@ void EndpointAppPBX::action_hangup_execute(void) void EndpointAppPBX::action_hangup_file(void) { struct route_param *rparam; - char *file, *content, *mode; + const char *file, *content, *mode; FILE *fp; /* get file / content */ @@ -2397,20 +1949,23 @@ void EndpointAppPBX::action_hangup_file(void) mode = "a"; else mode = "w"; - if (file[0] == '\0') - { - printlog("%3d action FILE no filename given.\n", ea_endpoint->ep_serial); - PERROR("EPOINT(%d): terminal %s: NO FILENAME GIVEN for 'file' action. see routing.conf\n", ea_endpoint->ep_serial, e_terminal); + if (file[0] == '\0') { + trace_header("ACTION file (no filename given)", DIRECTION_NONE); + end_trace(); return; } - if (!(fp = fopen(file, mode))) - { - printlog("%3d action FILE file '%s' cannot be opened. (errno = %d)\n", ea_endpoint->ep_serial, file, errno); - PERROR("EPOINT(%d): terminal %s: given file '%s' cannot be opened. see routing.conf\n", ea_endpoint->ep_serial, e_terminal, file); + if (!(fp = fopen(file, mode))) { + trace_header("ACTION file (failed to open)", DIRECTION_NONE); + add_trace("file", "name", "%s", file); + add_trace("file", "mode", "%s", (mode[0]=='w')?"write":"append"); + end_trace(); return; } - printlog("%3d action FILE file='%s' content='%s'\n", ea_endpoint->ep_serial, file, content); - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: writing file '%s' with content '%s'.\n", ea_endpoint->ep_serial, e_terminal, file, content); + trace_header("ACTION file", DIRECTION_NONE); + add_trace("file", "name", "%s", file); + add_trace("file", "mode", "%s", (mode[0]=='w')?"write":"append"); + add_trace("content", NULL, "%s", content); + end_trace(); fprintf(fp, "%s\n", content); fclose(fp); } @@ -2427,8 +1982,11 @@ void EndpointAppPBX::action_init_pick(void) if ((rparam = routeparam(e_action, PARAM_EXTENSIONS))) extensions = rparam->string_value; - printlog("%3d action PICK\n", ea_endpoint->ep_serial); - pick_call(extensions); + trace_header("ACTION pick", DIRECTION_NONE); + if (extensions) if (extensions[0]) + add_trace("extensions", NULL, "%s", extensions); + end_trace(); + pick_join(extensions); } @@ -2440,13 +1998,11 @@ void EndpointAppPBX::action_dialing_password(void) struct port_list *portlist = ea_endpoint->ep_portlist; /* prompt for password */ - if (e_extdialing[0] == '\0') - { + if (e_extdialing[0] == '\0') { /* give password tone */ set_tone(portlist, "password"); } else // ELSE!! - if (e_extdialing[1] == '\0') - { + if (e_extdialing[1] == '\0') { /* give password tone */ set_tone(portlist, "dialing"); } @@ -2456,10 +2012,10 @@ void EndpointAppPBX::action_dialing_password(void) return; /* more digits needed */ /* check the password */ - if (e_ext.password[0]=='\0' || (strlen(e_ext.password)==strlen(e_extdialing) && !!strcmp(e_ext.password,e_extdialing))) - { - printlog("%3d action PASSWORD WRITE password wrong\n", ea_endpoint->ep_serial); - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): password wrong %s\n", ea_endpoint->ep_serial, e_extdialing); + if (e_ext.password[0]=='\0' || (strlen(e_ext.password)==strlen(e_extdialing) && !!strcmp(e_ext.password,e_extdialing))) { + trace_header("ACTION password_write (wrong password)", DIRECTION_NONE); + add_trace("dialed", NULL, "%s", e_extdialing); + end_trace(); e_connectedmode = 0; e_dtmf = 0; new_state(EPOINT_STATE_OUT_DISCONNECT); @@ -2470,10 +2026,11 @@ void EndpointAppPBX::action_dialing_password(void) /* write caller id if ACTION_PASSWORD_WRITE was selected */ if (e_action) - if (e_action->index == ACTION_PASSWORD_WRITE) - { - append_callbackauth(e_terminal, &e_callbackinfo); - printlog("%3d action PASSWORD WRITE password written\n", ea_endpoint->ep_serial); + if (e_action->index == ACTION_PASSWORD_WRITE) { + append_callbackauth(e_ext.number, &e_callbackinfo); + trace_header("ACTION password_write (written)", DIRECTION_NONE); + add_trace("dialed", NULL, "%s", e_extdialing); + end_trace(); } /* make call state */ @@ -2482,8 +2039,8 @@ void EndpointAppPBX::action_dialing_password(void) if (e_ruleset) e_rule = e_ruleset->rule_first; e_action = NULL; - e_dialinginfo.number[0] = '\0'; - e_extdialing = e_dialinginfo.number; + e_dialinginfo.id[0] = '\0'; + e_extdialing = e_dialinginfo.id; set_tone(portlist, "dialpbx"); } @@ -2493,66 +2050,454 @@ void EndpointAppPBX::action_dialing_password_wr(void) } +/* process pots-retrieve + */ +void EndpointAppPBX::action_init_pots_retrieve(void) +{ +#ifdef ISDN_P_FXS_POTS + struct route_param *rparam; + struct port_list *portlist = ea_endpoint->ep_portlist; + class Port *port; + class Pfxs *ourfxs, *fxs; + int count = 0; + class Endpoint *epoint; + + /* check given call */ + if (!(rparam = routeparam(e_action, PARAM_POTS_CALL))) { + trace_header("ACTION pots-retrieve (no call given)", DIRECTION_NONE); + end_trace(); + + disconnect: + new_state(EPOINT_STATE_OUT_DISCONNECT); + message_disconnect_port(portlist, CAUSE_UNSPECIFIED, LOCATION_PRIVATE_LOCAL, ""); + set_tone(portlist, "cause_3f"); + e_action = NULL; + return; + } + + /* find call */ + port = find_port_id(portlist->port_id); + if (!port) + goto disconnect; + if ((port->p_type & PORT_CLASS_POTS_MASK) != PORT_CLASS_POTS_FXS) { + trace_header("ACTION pots-retrieve (call not of FXS type)", DIRECTION_NONE); + end_trace(); + goto disconnect; + } + ourfxs = (class Pfxs *)port; + + port = port_first; + while(port) { + if ((port->p_type & PORT_CLASS_POTS_MASK) == PORT_CLASS_POTS_FXS) { + fxs = (class Pfxs *)port; + if (fxs->p_m_mISDNport == ourfxs->p_m_mISDNport && fxs != ourfxs) { + count++; + if (count == rparam->integer_value) + break; + } + } + port = port->next; + } + if (!port) { + trace_header("ACTION pots-retrieve (call # does not exist)", DIRECTION_NONE); + end_trace(); + goto disconnect; + } + + /* release our call */ + ourfxs->hangup_ind(0); + + /* retrieve selected call */ + fxs->retrieve_ind(0); + + /* split if selected call is member of a 3pty */ + epoint = find_epoint_id(ACTIVE_EPOINT(fxs->p_epointlist)); + if (epoint && epoint->ep_app_type == EAPP_TYPE_PBX) { + PDEBUG(DEBUG_EPOINT, "EPOINT(%d) try spliting 3pty. this may fail because we don't have a 3pty.\n", epoint->ep_serial); + ((class EndpointAppPBX *)epoint->ep_app)->split_3pty(); + } +#endif +} + + +/* process pots-release + */ +void EndpointAppPBX::action_init_pots_release(void) +{ +#ifdef ISDN_P_FXS_POTS + struct route_param *rparam; + struct port_list *portlist = ea_endpoint->ep_portlist; + class Port *port; + class Pfxs *ourfxs, *fxs; + int count = 0; + + /* check given call */ + if (!(rparam = routeparam(e_action, PARAM_POTS_CALL))) { + trace_header("ACTION pots-release (no call given)", DIRECTION_NONE); + end_trace(); + + disconnect: + new_state(EPOINT_STATE_OUT_DISCONNECT); + message_disconnect_port(portlist, CAUSE_UNSPECIFIED, LOCATION_PRIVATE_LOCAL, ""); + set_tone(portlist, "cause_3f"); + e_action = NULL; + return; + } + + /* find call */ + port = find_port_id(portlist->port_id); + if (!port) + goto disconnect; + if ((port->p_type & PORT_CLASS_POTS_MASK) != PORT_CLASS_POTS_FXS) { + trace_header("ACTION pots-release (call not of FXS type)", DIRECTION_NONE); + end_trace(); + goto disconnect; + } + ourfxs = (class Pfxs *)port; + + port = port_first; + while(port) { + if ((port->p_type & PORT_CLASS_POTS_MASK) == PORT_CLASS_POTS_FXS) { + fxs = (class Pfxs *)port; + if (fxs->p_m_mISDNport == ourfxs->p_m_mISDNport && fxs != ourfxs) { + count++; + if (count == rparam->integer_value) + break; + } + } + port = port->next; + } + if (!port) { + trace_header("ACTION pots-release (call # does not exist)", DIRECTION_NONE); + end_trace(); + goto disconnect; + } + +#if 0 + /* disconnect our call */ + new_state(EPOINT_STATE_OUT_DISCONNECT); + message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, ""); + set_tone(portlist, "hangup"); + e_action = NULL; +#endif + + /* release selected call */ + fxs->hangup_ind(0); + + /* indicate timeout, so next action will be processed */ + process_dialing(1); +#endif +} + + +/* process pots-reject + */ +void EndpointAppPBX::action_init_pots_reject(void) +{ +#ifdef ISDN_P_FXS_POTS + struct port_list *portlist = ea_endpoint->ep_portlist; + class Port *port; + class Pfxs *ourfxs, *fxs; + + /* find call */ + port = find_port_id(portlist->port_id); + if (!port) + goto disconnect; + if ((port->p_type & PORT_CLASS_POTS_MASK) != PORT_CLASS_POTS_FXS) { + trace_header("ACTION pots-reject (call not of FXS type)", DIRECTION_NONE); + end_trace(); + disconnect: + new_state(EPOINT_STATE_OUT_DISCONNECT); + message_disconnect_port(portlist, CAUSE_UNSPECIFIED, LOCATION_PRIVATE_LOCAL, ""); + set_tone(portlist, "cause_3f"); + e_action = NULL; + return; + } + ourfxs = (class Pfxs *)port; + + port = port_first; + while(port) { + if ((port->p_type & PORT_CLASS_POTS_MASK) == PORT_CLASS_POTS_FXS) { + fxs = (class Pfxs *)port; + if (fxs->p_m_mISDNport == ourfxs->p_m_mISDNport && fxs != ourfxs) { + if (fxs->p_state == PORT_STATE_OUT_ALERTING) + break; + } + } + port = port->next; + } + if (!port) { + trace_header("ACTION pots-reject (no call waiting)", DIRECTION_NONE); + end_trace(); + goto disconnect; + } + + /* reject alerting call */ + fxs->reject_ind(0); + + /* indicate timeout, so next action will be processed */ + process_dialing(1); +#endif +} + + +/* process pots-answer + */ +void EndpointAppPBX::action_init_pots_answer(void) +{ +#ifdef ISDN_P_FXS_POTS + struct port_list *portlist = ea_endpoint->ep_portlist; + class Port *port; + class Pfxs *ourfxs, *fxs; + + /* find call */ + port = find_port_id(portlist->port_id); + if (!port) + goto disconnect; + if ((port->p_type & PORT_CLASS_POTS_MASK) != PORT_CLASS_POTS_FXS) { + trace_header("ACTION pots-answer (call not of FXS type)", DIRECTION_NONE); + end_trace(); + disconnect: + new_state(EPOINT_STATE_OUT_DISCONNECT); + message_disconnect_port(portlist, CAUSE_UNSPECIFIED, LOCATION_PRIVATE_LOCAL, ""); + set_tone(portlist, "cause_3f"); + e_action = NULL; + return; + } + ourfxs = (class Pfxs *)port; + + port = port_first; + while(port) { + if ((port->p_type & PORT_CLASS_POTS_MASK) == PORT_CLASS_POTS_FXS) { + fxs = (class Pfxs *)port; + if (fxs->p_m_mISDNport == ourfxs->p_m_mISDNport && fxs != ourfxs) { + if (fxs->p_state == PORT_STATE_OUT_ALERTING) + break; + } + } + port = port->next; + } + if (!port) { + trace_header("ACTION pots-answer (no call waiting)", DIRECTION_NONE); + end_trace(); + goto disconnect; + } + + /* release our call */ + ourfxs->hangup_ind(0); + + /* answer alerting call */ + fxs->answer_ind(0); +#endif +} + + +/* process pots-3pty + */ +void EndpointAppPBX::action_init_pots_3pty(void) +{ +#ifdef ISDN_P_FXS_POTS + struct port_list *portlist = ea_endpoint->ep_portlist; + class Port *port; + class Pfxs *ourfxs, *fxs, *fxs1 = NULL, *fxs2 = NULL; + class Endpoint *epoint; + int count = 0; + + /* find call */ + port = find_port_id(portlist->port_id); + if (!port) + goto disconnect; + if ((port->p_type & PORT_CLASS_POTS_MASK) != PORT_CLASS_POTS_FXS) { + trace_header("ACTION pots-3pty (call not of FXS type)", DIRECTION_NONE); + end_trace(); + disconnect: + new_state(EPOINT_STATE_OUT_DISCONNECT); + message_disconnect_port(portlist, CAUSE_UNSPECIFIED, LOCATION_PRIVATE_LOCAL, ""); + set_tone(portlist, "cause_3f"); + e_action = NULL; + return; + } + ourfxs = (class Pfxs *)port; + + port = port_first; + while(port) { + if ((port->p_type & PORT_CLASS_POTS_MASK) == PORT_CLASS_POTS_FXS) { + fxs = (class Pfxs *)port; + if (fxs->p_m_mISDNport == ourfxs->p_m_mISDNport && fxs != ourfxs) { + if (count == 0) + fxs1 = fxs; + if (count == 1) + fxs2 = fxs; + count++; + } + } + port = port->next; + } + if (count != 2) { + trace_header("ACTION pots-3pty (exactly two calls don't exist)", DIRECTION_NONE); + end_trace(); + goto disconnect; + } + + /* release our call */ + ourfxs->hangup_ind(0); + + /* retrieve latest active call */ + if (fxs2->p_m_fxs_age > fxs1->p_m_fxs_age) { + fxs2->retrieve_ind(0); + epoint = find_epoint_id(ACTIVE_EPOINT(fxs2->p_epointlist)); + } else { + fxs1->retrieve_ind(0); + epoint = find_epoint_id(ACTIVE_EPOINT(fxs2->p_epointlist)); + } + + if (!epoint) { + trace_header("ACTION pots-3pty (interal error: no endpoint)", DIRECTION_NONE); + end_trace(); + return; + } + + if (epoint->ep_app_type != EAPP_TYPE_PBX) { + trace_header("ACTION pots-3pty (interal error: endpoint not PBX type)", DIRECTION_NONE); + end_trace(); + return; + } + + /* bridge calls */ + if (((class EndpointAppPBX *)epoint->ep_app)->join_3pty_fxs()) { + trace_header("ACTION pots-3pty (interal error: join_3pty_fsx failed)", DIRECTION_NONE); + end_trace(); + return; + } +#endif +} + +/* process pots-transfer + */ +void EndpointAppPBX::action_init_pots_transfer(void) +{ +#ifdef ISDN_P_FXS_POTS + struct route_param *rparam; + struct port_list *portlist = ea_endpoint->ep_portlist; + class Port *port; + class Pfxs *ourfxs, *fxs, *fxs1 = NULL, *fxs2 = NULL; + int count = 0; + + /* check given call */ + if (!(rparam = routeparam(e_action, PARAM_POTS_CALL))) { + trace_header("ACTION pots-transfer (no call given)", DIRECTION_NONE); + end_trace(); + + disconnect: + new_state(EPOINT_STATE_OUT_DISCONNECT); + message_disconnect_port(portlist, CAUSE_UNSPECIFIED, LOCATION_PRIVATE_LOCAL, ""); + set_tone(portlist, "cause_3f"); + e_action = NULL; + return; + } + + /* find call */ + port = find_port_id(portlist->port_id); + if (!port) + goto disconnect; + if ((port->p_type & PORT_CLASS_POTS_MASK) != PORT_CLASS_POTS_FXS) { + trace_header("ACTION pots-transfer (call not of FXS type)", DIRECTION_NONE); + end_trace(); + goto disconnect; + } + ourfxs = (class Pfxs *)port; + + port = port_first; + while(port) { + if ((port->p_type & PORT_CLASS_POTS_MASK) == PORT_CLASS_POTS_FXS) { + fxs = (class Pfxs *)port; + if (fxs->p_m_mISDNport == ourfxs->p_m_mISDNport && fxs != ourfxs) { + if (count == 0) + fxs1 = fxs; + if (count == 1) + fxs2 = fxs; + count++; + } + } + port = port->next; + } + if (count != 2) { + trace_header("ACTION pots-transfer (exactly two calls don't exist)", DIRECTION_NONE); + end_trace(); + goto disconnect; + } + + /* retrieve call */ + if (fxs2->p_m_fxs_age > fxs1->p_m_fxs_age) + fxs2->retrieve_ind(0); + else + fxs1->retrieve_ind(0); + /* bridge calls */ + join_join_fxs(); +#endif +} + + /* general process dialing of incoming call * depending on the detected prefix, subfunctions above (action_*) will be * calles. */ -void EndpointAppPBX::process_dialing(void) +void EndpointAppPBX::process_dialing(int timeout) { struct port_list *portlist = ea_endpoint->ep_portlist; - struct message *message; + struct lcr_msg *message; struct route_param *rparam; + struct timeval current_time; + + /* set if timeout is active, or if timeout value was given due to timeout action */ + if (e_action_timeout.active) + timeout = 1; //#warning Due to HANG-BUG somewhere here, I added some HANG-BUG-DEBUGGING output that cannot be disabled. after bug has been found, this will be removed. //PDEBUG(~0, "HANG-BUG-DEBUGGING: entered porcess_dialing\n"); portlist = ea_endpoint->ep_portlist; /* check if we have a port instance linked to our epoint */ - if (!portlist) - { + if (!portlist) { portlist_error: - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): note: dialing call requires exactly one port object to process dialing. this case could happen due to a parked call. we end dialing here.\n", ea_endpoint->ep_serial, e_terminal); - e_action_timeout = 0; - e_match_timeout = 0; + PDEBUG(DEBUG_EPOINT, "EPOINT(%d): note: dialing call requires exactly one port object to process dialing. this case could happen due to a parked call. we end dialing here.\n", ea_endpoint->ep_serial, e_ext.number); + unsched_timer(&e_action_timeout); + unsched_timer(&e_match_timeout); return; } - if (portlist->next) - { + if (portlist->next) { goto portlist_error; } /* check nesting levels */ - if (++e_rule_nesting > RULE_NESTING) - { - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): rules are nesting too deep. (%d levels) check for infinite loops in routing.conf\n", ea_endpoint->ep_serial, e_rule_nesting); + if (++e_rule_nesting > RULE_NESTING) { + trace_header("ACTION (nesting too deep)", DIRECTION_NONE); + add_trace("max-levels", NULL, "%d", RULE_NESTING); + end_trace(); new_state(EPOINT_STATE_OUT_DISCONNECT); message_disconnect_port(portlist, CAUSE_UNSPECIFIED, LOCATION_PRIVATE_LOCAL, ""); set_tone(portlist, "cause_3f"); - e_action_timeout = 0; - e_match_timeout = 0; + unsched_timer(&e_action_timeout); + unsched_timer(&e_match_timeout); goto end; } //PDEBUG(~0, "HANG-BUG-DEBUGGING: before action-timeout processing\n"); /* process timeout */ - if (e_action_timeout) - { - e_action_timeout = 0; - if (e_state == EPOINT_STATE_CONNECT) - { + if (e_action && timeout) { /* e_action may be NULL, but e_action_timeout may still be set and must be ignored */ + unsched_timer(&e_action_timeout); + if (e_state == EPOINT_STATE_CONNECT) { PDEBUG(DEBUG_ROUTE|DEBUG_EPOINT, "EPOINT(%d): action timed out, but we already have connected, so we stop timer and continue.\n", ea_endpoint->ep_serial); goto end; } if (e_action->index == ACTION_DISCONNECT - || e_state == EPOINT_STATE_OUT_DISCONNECT) - { + || e_state == EPOINT_STATE_OUT_DISCONNECT) { /* release after disconnect */ - release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); + release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); goto end; } - release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, 0); + release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0, 0, 0); e_action = e_action->next; - if (!e_action) - { + if (!e_action) { /* nothing more, so we release */ PDEBUG(DEBUG_ROUTE|DEBUG_EPOINT, "EPOINT(%d): action timed out, and we have no next action, so we disconnect.\n", ea_endpoint->ep_serial); new_state(EPOINT_STATE_OUT_DISCONNECT); @@ -2560,32 +2505,28 @@ void EndpointAppPBX::process_dialing(void) set_tone(portlist, "cause_3f"); goto end; } - PDEBUG(DEBUG_ROUTE|DEBUG_EPOINT, "EPOINT(%d): continueing with action '%s'.\n", ea_endpoint->ep_serial, action_defs[e_action->index].name); goto action_timeout; } //PDEBUG(~0, "HANG-BUG-DEBUGGING: before setup/overlap state checking\n"); if (e_state!=EPOINT_STATE_IN_SETUP - && e_state!=EPOINT_STATE_IN_OVERLAP) - { - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): we are not in incomming setup/overlap state, so we ignore init/dialing process.\n", ea_endpoint->ep_serial, e_rule_nesting); - e_match_timeout = 0; + && e_state!=EPOINT_STATE_IN_OVERLAP) { + PDEBUG(DEBUG_EPOINT, "EPOINT(%d): we are not in incoming setup/overlap state, so we ignore init/dialing process.\n", ea_endpoint->ep_serial, e_rule_nesting); + unsched_timer(&e_match_timeout); goto end; } #if 0 /* check if we do menu selection */ - if (e_action==NUMB_ACTION_NONE && (e_dialinginfo.number[0]=='*' || e_dialinginfo.number[0]=='#')) + if (e_action==NUMB_ACTION_NONE && (e_dialinginfo.id[0]=='*' || e_dialinginfo.id[0]=='#')) /* do menu selection */ - if (e_ext.display_menu) - { - if (portlist->port_type==PORT_TYPE_DSS1_NT_IN || portlist->port_type==PORT_TYPE_DSS1_NT_OUT) /* only if the dialing terminal is an isdn telephone connected to an internal port */ - { - e_dialinginfo.number[0] = '\0'; + if (e_ext.display_menu) { + if (portlist->port_type==PORT_TYPE_DSS1_NT_IN || portlist->port_type==PORT_TYPE_DSS1_NT_OUT) { /* only if the dialing terminal is an isdn telephone connected to an internal port */ + e_dialinginfo.id[0] = '\0'; e_action = NUMB_ACTION_MENU; e_menu = 0; - process_dialing(); - e_match_timeout = 0; + process_dialing(0); + unsched_timer(&e_match_timeout); goto end; } /* invalid dialing */ @@ -2593,94 +2534,80 @@ void EndpointAppPBX::process_dialing(void) message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT); message->param.disconnectinfo.cause = CAUSE_INVALID; message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL; - } else - { + } else { message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY); SCPY(message->param.notifyinfo.display,get_isdn_cause(LOCATION_PRIVATE_LOCAL, epoint->e_ext.display_cause, param->disconnectinfo.location, param->disconnectinfo.cause)); } message_put(message); - logmessage(message); + logmessage(message->type, message->param, portlist->port_id, DIRECTION_OUT); } new_state(EPOINT_STATE_OUT_DISCONNECT); set_tone(portlist,"cause_1c"); - e_match_timeout = 0; + unsched_timer(&e_match_timeout); goto end; } #endif //PDEBUG(~0, "HANG-BUG-DEBUGGING: before e_action==NULL\n"); /* if no action yet, we will call try to find a matching rule */ - if (!e_action) - { + if (!e_action) { /* be sure that all selectors are initialized */ e_select = 0; /* check for external call */ - if (!strncmp(e_dialinginfo.number, "extern:", 7)) - { - e_extdialing = e_dialinginfo.number+7; + if (!strncmp(e_dialinginfo.id, "extern:", 7)) { + e_extdialing = e_dialinginfo.id+7; e_action = &action_external; goto process_action; } /* check for internal call */ - if (!strncmp(e_dialinginfo.number, "intern:", 7)) - { - e_extdialing = e_dialinginfo.number+7; + if (!strncmp(e_dialinginfo.id, "intern:", 7)) { + e_extdialing = e_dialinginfo.id+7; e_action = &action_internal; goto process_action; } - /* check for h323 call */ - if (!strncmp(e_dialinginfo.number, "h323:", 5)) - { - e_extdialing = e_dialinginfo.number+5; - e_action = &action_h323; - goto process_action; - } - /* check for chan call */ - if (!strncmp(e_dialinginfo.number, "chan:", 5)) - { - e_extdialing = e_dialinginfo.number+4; - e_action = &action_chan; - goto process_action; - } /* check for vbox call */ - if (!strncmp(e_dialinginfo.number, "vbox:", 5)) - { - e_extdialing = e_dialinginfo.number+5; + if (!strncmp(e_dialinginfo.id, "vbox:", 5)) { + e_extdialing = e_dialinginfo.id+5; e_action = &action_vbox; goto process_action; } - if (e_match_timeout && now_d>=e_match_timeout) - { + gettimeofday(¤t_time, NULL); + if (e_match_to_action && TIME_SMALLER(&e_match_timeout.timeout, ¤t_time)) { /* return timeout rule */ - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal '%s' dialing: '%s', timeout in ruleset '%s'\n", ea_endpoint->ep_serial, e_terminal, e_dialinginfo.number, e_ruleset->name); - e_match_timeout = 0; + PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal '%s' dialing: '%s', timeout in ruleset '%s'\n", ea_endpoint->ep_serial, e_ext.number, e_dialinginfo.id, e_ruleset->name); + unsched_timer(&e_match_timeout); e_action = e_match_to_action; + e_match_to_action = NULL; e_extdialing = e_match_to_extdialing; - printlog("%3d routing TIMEOUT processing action '%s' (line %d)\n", ea_endpoint->ep_serial, action_defs[e_action->index].name, e_action->line); - - } else - { + trace_header("ROUTING (timeout)", DIRECTION_NONE); + add_trace("action", NULL, "%s", action_defs[e_action->index].name); + add_trace("line", NULL, "%d", e_action->line); + end_trace(); + } else { //PDEBUG(~0, "HANG-BUG-DEBUGGING: before routing\n"); /* check for matching rule */ - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal '%s' dialing: '%s', checking matching rule of ruleset '%s'\n", ea_endpoint->ep_serial, e_terminal, e_dialinginfo.number, e_ruleset->name); - if (e_ruleset) - { + PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal '%s' dialing: '%s', checking matching rule of ruleset '%s'\n", ea_endpoint->ep_serial, e_ext.number, e_dialinginfo.id, e_ruleset->name); + if (e_ruleset) { e_action = route(e_ruleset); - if (e_action) - printlog("%3d routing MATCH processing action '%s' (line %d)\n", ea_endpoint->ep_serial, action_defs[e_action->index].name, e_action->line); - } else - { + if (e_action) { + trace_header("ACTION (match)", DIRECTION_NONE); + add_trace("action", NULL, "%s", action_defs[e_action->index].name); + add_trace("line", NULL, "%d", e_action->line); + end_trace(); + } + } else { e_action = &action_disconnect; - if (e_action) - printlog("%3d routing NO MAIN RULESET, DISCONNECTING! '%s'\n", ea_endpoint->ep_serial, action_defs[e_action->index].name); + if (e_action) { + trace_header("ACTION (no main ruleset, disconnecting)", DIRECTION_NONE); + end_trace(); + } } //PDEBUG(~0, "HANG-BUG-DEBUGGING: after routing\n"); } - if (!e_action) - { - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): no rule within the current ruleset matches yet.\n", ea_endpoint->ep_serial, e_terminal); + if (!e_action) { + PDEBUG(DEBUG_EPOINT, "EPOINT(%d): no rule within the current ruleset matches yet.\n", ea_endpoint->ep_serial, e_ext.number); goto display; } @@ -2690,67 +2617,59 @@ void EndpointAppPBX::process_dialing(void) action_timeout: /* set timeout */ - e_action_timeout = 0; - if (e_action->timeout) - { - e_action_timeout = now_d + e_action->timeout; + unsched_timer(&e_action_timeout); + if (e_action->timeout) { + schedule_timer(&e_action_timeout, e_action->timeout, 0); PDEBUG(DEBUG_ROUTE|DEBUG_EPOINT, "EPOINT(%d): action has a timeout of %d secods.\n", ea_endpoint->ep_serial, e_action->timeout); } process_action: /* check param proceeding / alerting / connect */ - if ((rparam = routeparam(e_action, PARAM_CONNECT))) - { + if ((rparam = routeparam(e_action, PARAM_CONNECT))) { /* NOTE: we may not change our state to connect, because dialing will then not possible */ e_dtmf = 1; memset(&e_connectinfo, 0, sizeof(e_connectinfo)); message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT); message_put(message); - logmessage(message); + logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT); } else - if ((rparam = routeparam(e_action, PARAM_ALERTING))) - { + if ((rparam = routeparam(e_action, PARAM_ALERTING))) { /* NOTE: we may not change our state to alerting, because dialing will then not possible */ memset(&e_connectinfo, 0, sizeof(e_connectinfo)); message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING); message_put(message); - logmessage(message); + logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT); } else - if ((rparam = routeparam(e_action, PARAM_PROCEEDING))) - { + if ((rparam = routeparam(e_action, PARAM_PROCEEDING))) { /* NOTE: we may not change our state to proceeding, because dialing will then not possible */ memset(&e_connectinfo, 0, sizeof(e_connectinfo)); message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING); message_put(message); - logmessage(message); + logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT); } - if (action_defs[e_action->index].init_func) - { - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: current action '%s' has a init function, so we call it...\n", ea_endpoint->ep_serial, e_terminal, action_defs[e_action->index].name); + if (action_defs[e_action->index].init_func) { + PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: current action '%s' has a init function, so we call it...\n", ea_endpoint->ep_serial, e_ext.number, action_defs[e_action->index].name); (this->*(action_defs[e_action->index].init_func))(); } if (e_state!=EPOINT_STATE_IN_SETUP - && e_state!=EPOINT_STATE_IN_OVERLAP) - { - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): AFTER init process: we are not in incomming setup/overlap state anymore, so we ignore further dialing process.\n", ea_endpoint->ep_serial, e_rule_nesting); + && e_state!=EPOINT_STATE_IN_OVERLAP) { + PDEBUG(DEBUG_EPOINT, "EPOINT(%d): AFTER init process: we are not in incoming setup/overlap state anymore, so we ignore further dialing process.\n", ea_endpoint->ep_serial, e_rule_nesting); goto display_action; } } /* show what we are doing */ - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal '%s' action: %s (dialing '%s')\n", ea_endpoint->ep_serial, e_terminal, action_defs[e_action->index].name, e_extdialing); + PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal '%s' action: %s (dialing '%s')\n", ea_endpoint->ep_serial, e_ext.number, action_defs[e_action->index].name, e_extdialing); /* go to action's dialing function */ - if (action_defs[e_action->index].dialing_func) - { - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: current action '%s' has a dialing function, so we call it...\n", ea_endpoint->ep_serial, e_terminal, action_defs[e_action->index].name); + if (action_defs[e_action->index].dialing_func) { + PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: current action '%s' has a dialing function, so we call it...\n", ea_endpoint->ep_serial, e_ext.number, action_defs[e_action->index].name); (this->*(action_defs[e_action->index].dialing_func))(); } /* display selected dialing action if enabled and still in setup state */ display_action: - if (e_action) - { + if (e_action) { if (e_action->index==ACTION_MENU || e_action->index==ACTION_REDIAL || e_action->index==ACTION_REPLY @@ -2763,21 +2682,18 @@ void EndpointAppPBX::process_dialing(void) if (!e_ext.display_dialing) goto end; if (e_state==EPOINT_STATE_IN_OVERLAP || e_state==EPOINT_STATE_IN_PROCEEDING || e_state==EPOINT_STATE_IN_ALERTING || e_state==EPOINT_STATE_CONNECT/* || e_state==EPOINT_STATE_IN_DISCONNECT || e_state==EPOINT_STATE_OUT_DISCONNECT*/) - if (portlist->port_type==PORT_TYPE_DSS1_NT_IN || portlist->port_type==PORT_TYPE_DSS1_NT_OUT) /* only if the dialing terminal is an isdn telephone connected to an internal port */ - { + if (portlist->port_type==PORT_TYPE_DSS1_NT_IN || portlist->port_type==PORT_TYPE_DSS1_NT_OUT) { /* only if the dialing terminal is an isdn telephone connected to an internal port */ message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY); - if (!e_action) - { - SPRINT(message->param.notifyinfo.display, "> %s", e_dialinginfo.number); - } else - { + if (!e_action) { + SPRINT(message->param.notifyinfo.display, "> %s", e_dialinginfo.id); + } else { SPRINT(message->param.notifyinfo.display, "%s%s%s", action_defs[e_action->index].name, (e_extdialing[0])?" ":"", e_extdialing); } - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s displaying interpreted dialing '%s'\n", ea_endpoint->ep_serial, e_terminal, message->param.notifyinfo.display); + PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s displaying interpreted dialing '%s'\n", ea_endpoint->ep_serial, e_ext.number, message->param.notifyinfo.display); message_put(message); - logmessage(message); + logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT); } end: @@ -2792,84 +2708,87 @@ void EndpointAppPBX::process_hangup(int cause, int location) char callertext[256], dialingtext[256]; int writeext = 0, i; - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal '%s'\n", ea_endpoint->ep_serial, e_terminal); - if (e_terminal[0]) - { - if (read_extension(&e_ext, e_terminal)) + PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal '%s'\n", ea_endpoint->ep_serial, e_ext.number); + if (e_ext.number[0]) { + if (read_extension(&e_ext, e_ext.number)) writeext = 0x10; - if (!e_start) - { + if (!e_start) { time(&e_start); e_stop = 0; } else if (!e_stop) time(&e_stop); - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): writing connect from %s to %s into logfile of %s\n", ea_endpoint->ep_serial, e_callerinfo.id, e_dialinginfo.number, e_terminal); - switch(e_dialinginfo.itype) - { - case INFO_ITYPE_H323: - SPRINT(dialingtext, "h323:%s", e_dialinginfo.number); - break; + PDEBUG(DEBUG_EPOINT, "EPOINT(%d): writing connect from %s to %s into logfile of %s\n", ea_endpoint->ep_serial, e_callerinfo.id, e_dialinginfo.id, e_ext.number); + switch(e_dialinginfo.itype) { case INFO_ITYPE_CHAN: - SPRINT(dialingtext, "chan:%s", e_dialinginfo.number); + SPRINT(dialingtext, "chan:%s", e_dialinginfo.id); break; - case INFO_ITYPE_INTERN: - SPRINT(dialingtext, "intern:%s", e_dialinginfo.number); + case INFO_ITYPE_ISDN_EXTENSION: + SPRINT(dialingtext, "intern:%s", e_dialinginfo.id); break; case INFO_ITYPE_VBOX: - SPRINT(dialingtext, "vbox:%s", e_dialinginfo.number); + SPRINT(dialingtext, "vbox:%s", e_dialinginfo.id); break; default: - SPRINT(dialingtext, "%s", e_dialinginfo.number); + SPRINT(dialingtext, "%s", e_dialinginfo.id); } if (e_callerinfo.id[0]) - SPRINT(callertext, "%s", numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype)); + SPRINT(callertext, "%s", numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype, options.national, options.international)); else SPRINT(callertext, "unknown"); /* allpy restriction */ if (!e_ext.anon_ignore && e_callerinfo.present==INFO_PRESENT_RESTRICTED) SPRINT(callertext, "anonymous"); - if (e_callerinfo.intern[0]) /* add intern if present */ - UNPRINT(strchr(callertext,'\0'), sizeof(callertext)-1+strlen(callertext), " (intern %s)", e_callerinfo.intern); - if (e_callerinfo.voip[0]) /* add voip if present */ - UNPRINT(strchr(callertext,'\0'), sizeof(callertext)-1+strlen(callertext), " (voip %s)", e_callerinfo.voip); - write_log(e_terminal, callertext, dialingtext, e_start, e_stop, 0, cause, location); + if (e_callerinfo.extension[0]) /* add intern if present */ + UNPRINT(strchr(callertext,'\0'), sizeof(callertext)-1+strlen(callertext), " (intern %s)", e_callerinfo.extension); + write_log(e_ext.number, callertext, dialingtext, e_start, e_stop, 0, cause, location); /* store last received call for reply-list */ - if (e_callerinfo.id[0] || e_callerinfo.intern[0]) - if (e_ext.anon_ignore || e_callerinfo.present!=INFO_PRESENT_RESTRICTED) - { - if (e_callerinfo.intern[0]) - SPRINT(callertext, "intern:%s", e_callerinfo.intern); + if (e_origin == 1) // outgoing to phone is incoming for user + if (e_callerinfo.id[0] || e_callerinfo.extension[0]) + if (e_ext.anon_ignore || e_callerinfo.present!=INFO_PRESENT_RESTRICTED) { + if (e_callerinfo.extension[0]) + SPRINT(callertext, "intern:%s", e_callerinfo.extension); else - SPRINT(callertext, "extern:%s", numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype)); - if (!!strcmp(callertext, e_ext.last_in[0])) - { + SPRINT(callertext, "extern:%s", numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype, options.national, options.international)); + if (!!strcmp(callertext, e_ext.last_in[0])) { i = MAX_REMEMBER-1; - while(i) - { + while(i) { UCPY(e_ext.last_in[i], e_ext.last_in[i-1]); i--; } SCPY(e_ext.last_in[0], callertext); writeext |= 1; /* store extension later */ - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: storing last received caller id '%s'.\n", ea_endpoint->ep_serial, e_terminal, e_ext.last_in[0]); + PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: storing last received caller id '%s'.\n", ea_endpoint->ep_serial, e_ext.number, e_ext.last_in[0]); } else - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: cannot store last received id '%s' because it is identical with the last one.\n", ea_endpoint->ep_serial, e_terminal, callertext); + PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: cannot store last received id '%s' because it is identical with the last one.\n", ea_endpoint->ep_serial, e_ext.number, callertext); } - } + /* store last made call for reply-list */ + if (e_origin == 0) // incoming from phone is outgoing for user + if (e_dialinginfo.id[0]) { + if (!!strcmp(e_dialinginfo.id, e_ext.last_out[0])) { + i = MAX_REMEMBER-1; + while(i) { + UCPY(e_ext.last_out[i], e_ext.last_out[i-1]); + i--; + } + SCPY(e_ext.last_out[0], e_dialinginfo.id); + writeext |= 1; /* store extension later */ + PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: storing last number '%s'.\n", ea_endpoint->ep_serial, e_ext.number, e_dialinginfo.id); + } else + PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: cannot store last number '%s' because it is identical with the last one.\n", ea_endpoint->ep_serial, e_ext.number, e_dialinginfo.id); + } + } /* write extension if needed */ if (writeext == 0x11) - write_extension(&e_ext, e_terminal); + write_extension(&e_ext, e_ext.number); - if (e_action) - { - if (action_defs[e_action->index].hangup_func) - { - PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: current action '%s' has a hangup function, so we call it...\n", ea_endpoint->ep_serial, e_terminal, action_defs[e_action->index].name); + if (e_action) { + if (action_defs[e_action->index].hangup_func) { + PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s: current action '%s' has a hangup function, so we call it...\n", ea_endpoint->ep_serial, e_ext.number, action_defs[e_action->index].name); (this->*(action_defs[e_action->index].hangup_func))(); } }