This commit is contained in:
Super User 2007-05-15 22:59:29 +02:00
parent 559ff64e30
commit fd2045584f
25 changed files with 403 additions and 2525 deletions

View File

@ -9,9 +9,6 @@
#* ** #* **
#*****************************************************************************/ #*****************************************************************************/
WITH-PBX = 42 # MUST BE SET for now
#WITH-H323 = 42 # comment this out, if no h323 should be compiled
#WITH-OPAL = 42 # NOT SUPPORTED YET
WITH-CRYPTO = 42 # comment this out, if no libcrypto should be used WITH-CRYPTO = 42 # comment this out, if no libcrypto should be used
# note: check your location and the names of libraries. # note: check your location and the names of libraries.
@ -19,12 +16,8 @@ WITH-CRYPTO = 42 # comment this out, if no libcrypto should be used
INSTALL_BIN = /usr/local/bin INSTALL_BIN = /usr/local/bin
INSTALL_DATA = /usr/local/pbx INSTALL_DATA = /usr/local/pbx
# give locations for the libraries (comment out H323_LIB and PWLIB_LIB, if they are installed on the system) # give locations for the libraries
LINUX_INCLUDE = -I/usr/src/linux/include LINUX_INCLUDE = -I/usr/src/linux/include
H323_INCLUDE = -I/usr/local/include/openh323
#H323_LIB = -L/usr/local/lib
#PWLIB_INCLUDE = -I/usr/local/include/ptlib/unix
#PWLIB_LIB = -L/usr/local/lib
# give location of the mISDN libraries # give location of the mISDN libraries
MISDNUSER_INCLUDE = -I../mISDNuser/include MISDNUSER_INCLUDE = -I../mISDNuser/include
@ -46,28 +39,10 @@ GENRC = ./genrc
GENEXT = ./genextension GENEXT = ./genextension
CFLAGS = -Wall -g -DINSTALL_DATA=\"$(INSTALL_DATA)\" CFLAGS = -Wall -g -DINSTALL_DATA=\"$(INSTALL_DATA)\"
CFLAGS += $(LINUX_INCLUDE) $(MISDNUSER_INCLUDE) CFLAGS += $(LINUX_INCLUDE) $(MISDNUSER_INCLUDE)
ifdef WITH-PBX
CFLAGS += -DPBX
endif
ifdef WITH-CRYPTO ifdef WITH-CRYPTO
CFLAGS += -DCRYPTO CFLAGS += -DCRYPTO
endif endif
CFLAGS_OPAL = $(CFLAGS)
CFLAGS_H323 = $(CFLAGS)
LIBDIR += $(MISDNUSER_LIB) LIBDIR += $(MISDNUSER_LIB)
ifdef WITH-OPAL
OPAL = opal.o opal_mgr.o opal_pbxep.o opal_pbxcon.o opal_pbxms.o
CFLAGS += -DOPAL
CFLAGS_OPAL += $(OPAL_INCLUDE) -DOPAL
LIBDIR += $(OPAL_LIB)
endif
ifdef WITH-H323
H323 = h323.o h323_ep.o h323_con.o h323_chan.o
LIBS += -lh323_linux_x86_r -lpt_linux_x86_r -ldl
CFLAGS += -DH323
CFLAGS_H323 += $(H323_INCLUDE) $(PWLIB_INCLUDE) -DH323INCLUDE -DH323 -D_REENTRANT -DPBYTE_ORDER=PLITTLE_ENDIAN -DP_PTHREADS -DP_HAS_SEMAPHORES -DPHAS_TEMPLATES -DP_LINUX -DPTRACING
LIBDIR += $(H323_LIB) $(PWLIB_LIB)
endif
ifdef WITH-CRYPTO ifdef WITH-CRYPTO
LIBDIR += -L/usr/local/ssl/lib LIBDIR += -L/usr/local/ssl/lib
CFLAGS += -I/usr/local/ssl/include CFLAGS += -I/usr/local/ssl/include
@ -92,7 +67,7 @@ all: $(PBXADMIN) $(PBX) $(GEN) $(GENW) $(GENRC) $(GENEXT)
@exit @exit
main.o: main.c *.h Makefile main.o: main.c *.h Makefile
$(CC) -c $(CFLAGS_H323) main.c -o main.o $(CC) -c $(CFLAGS) main.c -o main.o
message.o: message.c *.h Makefile message.o: message.c *.h Makefile
$(CC) -c $(CFLAGS) message.c -o message.o $(CC) -c $(CFLAGS) message.c -o message.o
@ -103,9 +78,6 @@ options.o: options.c *.h Makefile
interface.o: interface.c *.h Makefile interface.o: interface.c *.h Makefile
$(CC) -c $(CFLAGS) interface.c -o interface.o $(CC) -c $(CFLAGS) interface.c -o interface.o
h323conf.o: h323conf.c *.h Makefile
$(CC) -c $(CFLAGS) h323conf.c -o h323conf.o
extension.o: extension.c *.h Makefile extension.o: extension.c *.h Makefile
$(CC) -c $(CFLAGS) extension.c -o extension.o $(CC) -c $(CFLAGS) extension.c -o extension.o
@ -184,18 +156,6 @@ tones.o: tones.c *.h Makefile
crypt.o: crypt.cpp *.h Makefile crypt.o: crypt.cpp *.h Makefile
$(CC) -c $(CFLAGS) crypt.cpp -o crypt.o $(CC) -c $(CFLAGS) crypt.cpp -o crypt.o
h323.o: h323.cpp *.h Makefile
$(CC) -c $(CFLAGS_H323) h323.cpp -o h323.o
h323_ep.o: h323_ep.cpp *.h Makefile
$(CC) -c $(CFLAGS_H323) h323_ep.cpp -o h323_ep.o
h323_chan.o: h323_chan.cpp *.h Makefile
$(CC) -c $(CFLAGS_H323) h323_chan.cpp -o h323_chan.o
h323_con.o: h323_con.cpp *.h Makefile
$(CC) -c $(CFLAGS_H323) h323_con.cpp -o h323_con.o
genext.o: genext.c *.h Makefile genext.o: genext.c *.h Makefile
$(CC) -c $(CFLAGS) genext.c -o genext.o $(CC) -c $(CFLAGS) genext.c -o genext.o
@ -210,11 +170,9 @@ admin_server.o: admin_server.c *.h Makefile
# $(CC) $(LIBDIR) $(CFLAGS) -lm wizzard.c \ # $(CC) $(LIBDIR) $(CFLAGS) -lm wizzard.c \
# -o $(WIZZARD) # -o $(WIZZARD)
$(PBX): $(H323) $(OPAL) \ $(PBX): main.o \
main.o \
options.o \ options.o \
interface.o \ interface.o \
h323conf.o \
extension.o \ extension.o \
cause.o \ cause.o \
alawulaw.o \ alawulaw.o \
@ -237,11 +195,10 @@ $(PBX): $(H323) $(OPAL) \
callpbx.o \ callpbx.o \
callchan.o \ callchan.o \
admin_server.o admin_server.o
$(LD) $(LIBDIR) $(H323) $(OPAL) \ $(LD) $(LIBDIR) \
main.o \ main.o \
options.o \ options.o \
interface.o \ interface.o \
h323conf.o \
extension.o \ extension.o \
cause.o \ cause.o \
alawulaw.o \ alawulaw.o \
@ -318,9 +275,6 @@ install:
echo "NOTE: numbering_int.conf is obsolete, please use routing." ; fi echo "NOTE: numbering_int.conf is obsolete, please use routing." ; fi
@if test -a $(INSTALL_DATA)/numbering_ext.conf ; then \ @if test -a $(INSTALL_DATA)/numbering_ext.conf ; then \
echo "NOTE: numbering_ext.conf is obsolete, please use routing." ; fi echo "NOTE: numbering_ext.conf is obsolete, please use routing." ; fi
@if test -a $(INSTALL_DATA)/h323_gateway.conf ; then \
echo "NOTE: h323_gateway.conf already exists, not changed." ; else \
cp -v default/h323_gateway.conf $(INSTALL_DATA) ; fi
@if test -a $(INSTALL_DATA)/directory.list ; then \ @if test -a $(INSTALL_DATA)/directory.list ; then \
echo "NOTE: directory.list already exists, not changed." ; else \ echo "NOTE: directory.list already exists, not changed." ; else \
cp -v default/directory.list $(INSTALL_DATA) ; fi cp -v default/directory.list $(INSTALL_DATA) ; fi

4
README
View File

@ -334,8 +334,4 @@ Changes in Version 3.4
- Timeout condition seems to work now. - Timeout condition seems to work now.
- Timeout action seems to work now. - Timeout action seems to work now.
What you might expect in later versions
-> ISDN over IP (proprietary solution)
-> OPAL, with a new interface between user space audio and kernel space audio (SIP / H323)
-> (maybe later) Kernel space RTP that makes VoIP reeeeeeeeeeeeally fast!

View File

@ -67,7 +67,7 @@ char *numberrize_callerinfo(char *string, int ntype)
/* /*
* process init 'internal' / 'external' / 'h323' / 'chan' / 'vbox-record' / 'partyline'... * process init 'internal' / 'external' / 'chan' / 'vbox-record' / 'partyline'...
*/ */
void EndpointAppPBX::_action_init_call(int chan) void EndpointAppPBX::_action_init_call(int chan)
{ {
@ -374,432 +374,6 @@ void EndpointAppPBX::action_dialing_external(void)
} }
#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) void EndpointAppPBX::action_dialing_chan(void)
{ {
struct port_list *portlist = ea_endpoint->ep_portlist; struct port_list *portlist = ea_endpoint->ep_portlist;
@ -1412,9 +986,6 @@ void EndpointAppPBX::_action_redial_reply(int in)
if (!strncmp(last, "intern:", 7)) if (!strncmp(last, "intern:", 7))
SPRINT(message->param.notifyinfo.display, "(%d) %s int", e_select+1, last+7); SPRINT(message->param.notifyinfo.display, "(%d) %s int", e_select+1, last+7);
else 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)) if (!strncmp(last, "chan:", 4))
SPRINT(message->param.notifyinfo.display, "(%d) %s chan", e_select+1, last+5); SPRINT(message->param.notifyinfo.display, "(%d) %s chan", e_select+1, last+5);
else else
@ -2629,13 +2200,6 @@ void EndpointAppPBX::process_dialing(void)
e_action = &action_internal; e_action = &action_internal;
goto process_action; 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 */ /* check for chan call */
if (!strncmp(e_dialinginfo.number, "chan:", 5)) if (!strncmp(e_dialinginfo.number, "chan:", 5))
{ {
@ -2808,9 +2372,6 @@ void EndpointAppPBX::process_hangup(int cause, int location)
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); 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) switch(e_dialinginfo.itype)
{ {
case INFO_ITYPE_H323:
SPRINT(dialingtext, "h323:%s", e_dialinginfo.number);
break;
case INFO_ITYPE_CHAN: case INFO_ITYPE_CHAN:
SPRINT(dialingtext, "chan:%s", e_dialinginfo.number); SPRINT(dialingtext, "chan:%s", e_dialinginfo.number);
break; break;

View File

@ -236,9 +236,6 @@ int admin_route(struct admin_queue **responsep)
case ACTION_EXTERNAL: case ACTION_EXTERNAL:
apppbx->e_action = &action_external; apppbx->e_action = &action_external;
break; break;
case ACTION_H323:
apppbx->e_action = &action_h323;
break;
case ACTION_CHAN: case ACTION_CHAN:
apppbx->e_action = &action_chan; apppbx->e_action = &action_chan;
break; break;

View File

@ -146,6 +146,94 @@ void EndpointAppPBX::new_state(int state)
} }
/* screen caller id
* out==0: incomming caller id, out==1: outgoing caller id
*/
void EndpointAppPBX::screen(int out, char *id, int idsize, int *type, int *present)
{
struct interface *interface;
interface = interface_first;
while(interface)
{
if (!strcmp(e_callerinfo.interface, interface->name))
{
break;
}
interface = interface->next;
}
add logging
if (interface)
{
/* screen incoming caller id */
if (!out)
{
/* check for MSN numbers, use first MSN if no match */
msn1 = NULL;
ifmsn = interface->ifmsn;
while(ifmns)
{
if (!msn1)
msn1 = ifmns->msn;
if (!strcmp(ifmns->mns, id))
{
break;
}
ifmsn = ifmsn->next;
}
if (!ifmns && mns1) // not in list, first msn given
UNCPY(id, msn1, idsize);
id[idsize-1] = '\0';
}
/* check screen list */
if (out)
iscreen = interface->ifscreen_out;
else
iscreen = interface->ifscreen_in;
while (ifscreen)
{
if (ifcreen->match_type==-1 || ifscreen->match_type==*type)
if (ifcreen->match_present==-1 || ifscreen->match_present==*present)
{
if (strchr(ifcreen->match_id,'%'))
{
if (!strncmp(ifscreen->match_id, id, strchr(ifscreen->match_id,'%')-ifscreen->match_id))
break;
} else
{
if (!strcmp(ifscreen->match_id, id))
break;
}
}
ifscreen = ifscreen->next;
}
if (ifscreen) // match
{
if (ifscren->result_type != -1)
*type = ifscreen->result_type;
if (ifscren->result_present != -1)
*present = ifscreen->result_present;
if (strchr(ifscreen->match_id,'%'))
{
SCPY(suffix, strchr(ifscreen->match_id,'%') - ifscreen->match_id + id);
UNCPY(id, ifscreen->result_id);
id[idsize-1] = '\0';
if (strchr(ifscreen->result_id,'%'))
{
*strchr(ifscreen->result_id,'%') = '\0';
UNCAT(id, suffix, idsize);
id[idsize-1] = '\0';
}
} else
{
UNCPY(id, ifscreen->result_id, idsize);
id[idsize-1] = '\0';
}
}
}
}
/* release call and port (as specified) /* release call and port (as specified)
*/ */
void EndpointAppPBX::release(int release, int calllocation, int callcause, int portlocation, int portcause) void EndpointAppPBX::release(int release, int calllocation, int callcause, int portlocation, int portcause)
@ -1138,91 +1226,6 @@ void EndpointAppPBX::out_setup(void)
} }
break; break;
#ifdef H323
/* *********************** h323 call */
case INFO_ITYPE_H323:
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing H323: '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.number);
/* alloc port */
if (!(port = new H323Port(PORT_TYPE_H323_OUT, "H323-out", &port_settings)))
{
PERROR("EPOINT(%d) no mem for port\n", ea_endpoint->ep_serial);
break;
}
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocated port %s\n", ea_endpoint->ep_serial, port->p_name);
memset(&dialinginfo, 0, sizeof(dialinginfo));
SCPY(dialinginfo.number, e_dialinginfo.number);
dialinginfo.itype = INFO_ITYPE_H323;
dialinginfo.ntype = e_dialinginfo.ntype;
portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, 0);
if (!portlist)
{
PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
delete port;
release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
return;
}
//printf("INTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.number);
message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, 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));
//terminal SCPY(message->param.setup.from_terminal, e_terminal);
//terminal if (e_dialinginfo.number)
//terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.number);
/* handle restricted caller ids */
apply_callerid_restriction(e_ext.anon_ignore, port->p_type, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.voip, message->param.setup.callerinfo.intern, message->param.setup.callerinfo.name);
apply_callerid_restriction(e_ext.anon_ignore, port->p_type, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, NULL, message->param.setup.redirinfo.voip, message->param.setup.redirinfo.intern, 0);
/* display callerid if desired for extension */
SCPY(message->param.setup.callerinfo.display, apply_callerid_display(message->param.setup.callerinfo.id, message->param.setup.callerinfo.itype, message->param.setup.callerinfo.ntype, message->param.setup.callerinfo.present, message->param.setup.callerinfo.screen, message->param.setup.callerinfo.voip, message->param.setup.callerinfo.intern, message->param.setup.callerinfo.name));
message_put(message);
logmessage(message);
break;
#endif
#ifdef SIP
/* *********************** sip call */
case INFO_ITYPE_SIP:
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing SIP: '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.number);
/* alloc port */
if (!(port = new Psip(PORT_TYPE_SIP_OUT, 0, 0, e_dialinginfo.number)))
{
PERROR("EPOINT(%d) no mem for port\n", ea_endpoint->ep_serial);
break;
}
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocated port %s\n", ea_endpoint->ep_serial, port->p_name);
memset(&dialinginfo, 0, sizeof(dialinginfo));
SCPY(dialinginfo.number, e_dialinginfo.number);
dialinginfo.itype = INFO_ITYPE_SIP;
dialinginfo.ntype = e_dialinginfo.ntype;
portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, 0);
if (!portlist)
{
PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
delete port;
release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, call, port */
return;
}
//printf("INTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.number);
message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, 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));
//terminal SCPY(message->param.setup.from_terminal, e_terminal);
//terminal if (e_dialinginfo.number)
//terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.number);
/* handle restricted caller ids */
apply_callerid_restriction(e_ext.anon_ignore, port->p_type, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.voip, message->param.setup.callerinfo.intern, message->param.setup.callerinfo.name);
apply_callerid_restriction(e_ext.anon_ignore, port->p_type, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, NULL, message->param.setup.redirinfo.voip, message->param.setup.redirinfo.intern, 0);
/* display callerid if desired for extension */
SCPY(message->param.setup.callerinfo.display, apply_callerid_display(message->param.setup.callerinfo.id, message->param.setup.callerinfo.itype, message->param.setup.callerinfo.ntype, message->param.setup.callerinfo.present, message->param.setup.callerinfo.screen, message->param.setup.callerinfo.voip, message->param.setup.callerinfo.intern, message->param.setup.callerinfo.name));
message_put(message);
logmessage(message);
break;
#endif
/* *********************** external call */ /* *********************** external call */
default: default:
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.number); PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.number);
@ -1573,7 +1576,6 @@ void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, un
{ {
struct message *message; struct message *message;
char buffer[256]; char buffer[256];
struct interface *interface;
char extension[32]; char extension[32];
char extension1[32]; char extension1[32];
char *p; char *p;
@ -1587,100 +1589,20 @@ void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, un
memcpy(&e_capainfo, &param->setup.capainfo, sizeof(e_capainfo)); memcpy(&e_capainfo, &param->setup.capainfo, sizeof(e_capainfo));
e_dtmf = param->setup.dtmf; e_dtmf = param->setup.dtmf;
/* check where the call is from */ /* screen by interface */
if (e_callerinfo.interface[0]) if (e_callerinfo.interface[0])
{ {
interface = interface_first; /* screen incoming caller id */
while(interface) screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present);
{
if (!strcmp(e_callerinfo.interface, interface->name))
{
break;
}
interface = interface->next;
}
if (interface)
{
/* check for MSN numbers, use first MSN if no match */
msn1 = NULL;
ifmsn = interface->ifmsn;
while(ifmns)
{
if (!msn1)
msn1 = ifmns->msn;
if (!strcmp(ifmns->mns, e_callerinfo.id))
{
break;
}
ifmsn = ifmsn->next;
}
if (!ifmns && mns1) // not in list, first msn given
SCPY(p_callerinfo.id, msn1);
/* interface is known */
if (interface->iftype==IF_INTERN)
{
/* interface is internal */
if (interface->extensions[0])
{
hier denken
/* extensions are assigned to interface */
p = interface->extensions;
extension1[0] = '\0';
while(*p)
{
extension[0] = '\0';
while(*p!=',' && *p!='\0')
SCCAT(extension, *p++);
if (*p == ',')
p++;
if (!extension1[0])
SCPY(extension1, extension);
if (!strcmp(extension, e_callerinfo.id))
break;
extension[0] = '\0'; /* NOTE: empty if we did not find */
}
if (extension[0])
{
/* id was found at extension's list */
e_callerinfo.itype = INFO_ITYPE_INTERN;
SCPY(e_callerinfo.intern, extension);
} else
if (extension1[0])
{
/* if was provided by default */
e_callerinfo.itype = INFO_ITYPE_INTERN;
printlog("%3d endpoint INTERFACE Caller ID '%s' not in list for interface '%s', using first ID '%s'.\n", ea_endpoint->ep_serial, e_callerinfo.id, interface->name, extension1);
SCPY(e_callerinfo.intern, extension1);
}
} else
{
/* no extension given, so we use the caller id */
e_callerinfo.itype = INFO_ITYPE_INTERN;
SCPY(e_callerinfo.intern, e_callerinfo.id);
}
} else
{
/* interface is external */
e_callerinfo.intern[0] = '\0';
}
} else
{
/* interface is unknown */
message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
new_state(EPOINT_STATE_OUT_DISCONNECT);
set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
e_terminal[0] = '\0'; /* no terminal */
return;
}
} }
colp, outclip, outcolp
/* process extension */
if (e_callerinfo.itype == INFO_ITYPE_INTERN) if (e_callerinfo.itype == INFO_ITYPE_INTERN)
{ {
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is internal\n", ea_endpoint->ep_serial); PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is extension\n", ea_endpoint->ep_serial);
/* port makes call from extension */ /* port makes call from extension */
SCPY(e_callerinfo.id, e_callerinfo.intern); SCPY(e_callerinfo.intern, e_callerinfo.id);
SCPY(e_terminal, e_callerinfo.intern); SCPY(e_terminal, e_callerinfo.intern);
SCPY(e_terminal_interface, e_callerinfo.interface); SCPY(e_terminal_interface, e_callerinfo.interface);
} else } else
@ -1689,7 +1611,7 @@ void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, un
} }
printlog("%3d incoming %s='%s'%s%s%s%s dialing='%s'\n", printlog("%3d incoming %s='%s'%s%s%s%s dialing='%s'\n",
ea_endpoint->ep_serial, ea_endpoint->ep_serial,
(e_callerinfo.intern[0])?"SETUP from intern":"SETUP from extern", (e_callerinfo.intern[0])?"SETUP from extension":"SETUP from extern",
(e_callerinfo.intern[0])?e_callerinfo.intern:e_callerinfo.id, (e_callerinfo.intern[0])?e_callerinfo.intern:e_callerinfo.id,
(e_callerinfo.present==INFO_PRESENT_RESTRICTED)?" anonymous":"", (e_callerinfo.present==INFO_PRESENT_RESTRICTED)?" anonymous":"",
(e_redirinfo.id[0])?"redirected='":"", (e_redirinfo.id[0])?"redirected='":"",
@ -2204,6 +2126,13 @@ void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type,
e_start = now; e_start = now;
/* screen by interface */
if (e_callerinfo.interface[0])
{
/* screen incoming caller id */
screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present);
}
/* screen connected name */ /* screen connected name */
if (e_ext.name[0]) if (e_ext.name[0])
SCPY(e_connectinfo.name, e_ext.name); SCPY(e_connectinfo.name, e_ext.name);
@ -2260,18 +2189,6 @@ void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type,
e_connectinfo.present = INFO_PRESENT_ALLOWED; e_connectinfo.present = INFO_PRESENT_ALLOWED;
} }
} }
if (portlist->port_type==PORT_TYPE_H323_OUT) /* h323 extension answered */
{
SCPY(e_connectinfo.voip, port->p_dialinginfo.number);
e_connectinfo.present = INFO_PRESENT_ALLOWED;
// e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
}
if (portlist->port_type==PORT_TYPE_SIP_OUT) /* sip extension answered */
{
SCPY(e_connectinfo.voip, port->p_dialinginfo.number);
e_connectinfo.present = INFO_PRESENT_ALLOWED;
// e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
}
} }
message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type); message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, message_type);
memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info)); memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
@ -3172,6 +3089,14 @@ void EndpointAppPBX::call_connect(struct port_list *portlist, int message_type,
{ {
message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT); message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
memcpy(&message->param, param, sizeof(union parameter)); memcpy(&message->param, param, sizeof(union parameter));
/* screen by interface */
if (e_connectinfo.interface[0])
{
/* screen incoming caller id */
screen(1, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present);
}
memcpy(&message->param.connnectinfo, e_connectinfo);
/* screen clip if prefix is required */ /* screen clip if prefix is required */
if (e_terminal[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0]) if (e_terminal[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0])
{ {
@ -3179,19 +3104,23 @@ void EndpointAppPBX::call_connect(struct port_list *portlist, int message_type,
SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype)); SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype));
message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN; message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
} }
/* use internal caller id */ /* use internal caller id */
if (e_terminal[0] && e_connectinfo.intern[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore)) if (e_terminal[0] && e_connectinfo.intern[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
{ {
SCPY(message->param.connectinfo.id, e_connectinfo.intern); SCPY(message->param.connectinfo.id, e_connectinfo.intern);
message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN; message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
} }
/* handle restricted caller ids */ /* 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.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);
/* display callerid if desired for extension */ /* 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.voip, message->param.connectinfo.intern, message->param.connectinfo.name));
/* use conp, if enabld */ /* use conp, if enabld */
if (!e_ext.centrex) if (!e_ext.centrex)
message->param.connectinfo.name[0] = '\0'; message->param.connectinfo.name[0] = '\0';
/* send connect */ /* send connect */
message_put(message); message_put(message);
logmessage(message); logmessage(message);
@ -3416,6 +3345,13 @@ void EndpointAppPBX::call_setup(struct port_list *portlist, int message_type, un
memcpy(&e_redirinfo, &param->setup.redirinfo, sizeof(e_redirinfo)); memcpy(&e_redirinfo, &param->setup.redirinfo, sizeof(e_redirinfo));
memcpy(&e_capainfo, &param->setup.capainfo, sizeof(e_capainfo)); memcpy(&e_capainfo, &param->setup.capainfo, sizeof(e_capainfo));
/* screen by interface */
if (e_callerinfo.interface[0])
{
/* screen incoming caller id */
screen(1, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present);
}
/* process (voice over) data calls */ /* process (voice over) data calls */
if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO) if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO)
{ {
@ -4264,32 +4200,6 @@ void EndpointAppPBX::logmessage(struct message *message)
pdss1->p_m_mISDNport->portnum pdss1->p_m_mISDNport->portnum
); );
} }
if (port->p_type == PORT_TYPE_H323_OUT)
{
printlog("%3d outgoing SETUP from %s='%s'%s%s%s%s to h323='%s'\n",
ea_endpoint->ep_serial,
(message->param.setup.callerinfo.intern[0])?"intern":"extern",
(message->param.setup.callerinfo.intern[0])?e_callerinfo.intern:e_callerinfo.id,
(message->param.setup.callerinfo.present==INFO_PRESENT_RESTRICTED)?" anonymous":"",
(message->param.setup.redirinfo.id[0])?"redirected='":"",
message->param.setup.redirinfo.id,
(message->param.setup.redirinfo.id[0])?"'":"",
message->param.setup.dialinginfo.number
);
}
if (port->p_type == PORT_TYPE_SIP_OUT)
{
printlog("%3d outgoing SETUP from %s='%s'%s%s%s%s to sip='%s'\n",
ea_endpoint->ep_serial,
(message->param.setup.callerinfo.intern[0])?"intern":"extern",
(message->param.setup.callerinfo.intern[0])?e_callerinfo.intern:e_callerinfo.id,
(message->param.setup.callerinfo.present==INFO_PRESENT_RESTRICTED)?" anonymous":"",
(message->param.setup.redirinfo.id[0])?"redirected='":"",
message->param.setup.redirinfo.id,
(message->param.setup.redirinfo.id[0])?"'":"",
message->param.setup.dialinginfo.number
);
}
if (port->p_type == PORT_TYPE_VBOX_OUT) if (port->p_type == PORT_TYPE_VBOX_OUT)
{ {
printlog("%3d outgoing SETUP from %s='%s'%s%s%s%s to vbox='%s'\n", printlog("%3d outgoing SETUP from %s='%s'%s%s%s%s to vbox='%s'\n",

View File

@ -255,7 +255,8 @@ CallPBX::CallPBX(class Endpoint *epoint) : Call(epoint)
c_caller_id[0] = '\0'; c_caller_id[0] = '\0';
c_dialed[0] = '\0'; c_dialed[0] = '\0';
c_todial[0] = '\0'; c_todial[0] = '\0';
c_mixer = 0; c_pid = getpid();
c_updatebridge = 0;
c_partyline = 0; c_partyline = 0;
/* initialize a relation only to the calling interface */ /* initialize a relation only to the calling interface */
@ -298,23 +299,26 @@ CallPBX::~CallPBX()
} }
/* mixer sets the mixer of hisax bchannels /* bridge sets the audio flow of all bchannels assiociated to 'this' call
* the mixer() will set the mixer for the hisax ports which is done * also it changes and notifies active/hold/conference states
* at kernel space.
*/ */
void CallPBX::mixer(void) void CallPBX::bridge(void)
{ {
struct call_relation *relation; struct call_relation *relation;
struct message *message; struct message *message;
int numconnect, relations; int numconnect = 0, relations = 0;
class Endpoint *epoint; class Endpoint *epoint;
struct port_list *portlist; struct port_list *portlist;
class Port *port; class Port *port;
int nodata = 1; int allmISDN = 0; // relations that are no mISDN
relation = c_relation; relation = c_relation;
while(relation) while(relation)
{ {
/* count all relations */
relations++;
/* check for relation's objects */
epoint = find_epoint_id(relation->epoint_id); epoint = find_epoint_id(relation->epoint_id);
if (!epoint) if (!epoint)
{ {
@ -325,7 +329,7 @@ void CallPBX::mixer(void)
portlist = epoint->ep_portlist; portlist = epoint->ep_portlist;
if (!portlist) if (!portlist)
{ {
PDEBUG((DEBUG_CALL|DEBUG_PORT), "ignoring relation without interfaces.\n"); PDEBUG((DEBUG_CALL|DEBUG_PORT), "ignoring relation without port object.\n");
//#warning testing: keep on hold until single audio stream available //#warning testing: keep on hold until single audio stream available
relation->channel_state = CHANNEL_STATE_HOLD; relation->channel_state = CHANNEL_STATE_HOLD;
relation = relation->next; relation = relation->next;
@ -342,38 +346,44 @@ void CallPBX::mixer(void)
port = find_port_id(portlist->port_id); port = find_port_id(portlist->port_id);
if (!port) if (!port)
{ {
PDEBUG((DEBUG_CALL|DEBUG_PORT), "software error: relation without existing port.\n"); PDEBUG((DEBUG_CALL|DEBUG_PORT), "ignoring relation without existing port object.\n");
relation = relation->next; relation = relation->next;
continue; continue;
} }
if (port->p_record)
{
PDEBUG(DEBUG_CALL|DEBUG_PORT, "mixer(): relation ep%d does recording, so we must get data from all members.\n", epoint->ep_serial);
if (nodata)
{
PDEBUG(DEBUG_CALL|DEBUG_PORT, "mixer(): at least one endpoint wants data.\n");
nodata = 0;
}
}
if ((port->p_type&PORT_CLASS_MASK)!=PORT_CLASS_mISDN) if ((port->p_type&PORT_CLASS_MASK)!=PORT_CLASS_mISDN)
{ {
PDEBUG((DEBUG_CALL|DEBUG_PORT), "ignoring relation ep%d because it is not mISDN.\n", epoint->ep_serial); PDEBUG((DEBUG_CALL|DEBUG_PORT), "ignoring relation ep%d because it's port is not mISDN.\n", epoint->ep_serial);
if (nodata) if (allmISDN)
{ {
PDEBUG((DEBUG_CALL|DEBUG_PORT), "not all endpoints are mISDN.\n"); PDEBUG((DEBUG_CALL|DEBUG_PORT), "not all endpoints are mISDN.\n");
nodata = 0; allmISDN = 0;
} }
relation = relation->next; relation = relation->next;
continue; continue;
} }
// remove unconnected parties from conference, also remove remotely disconnected parties so conference will not be disturbed. relation = relation->next;
}
/* we notify all relations about rxdata. */
relation = c_relation;
while(relation)
{
/* count connected relations */
if ((relation->channel_state == CHANNEL_STATE_CONNECT)
&& (relation->rx_state != NOTIFY_STATE_SUSPEND)
&& (relation->rx_state != NOTIFY_STATE_HOLD))
numconnect ++;
/* remove unconnected parties from conference, also remove remotely disconnected parties so conference will not be disturbed. */
if (relation->channel_state == CHANNEL_STATE_CONNECT if (relation->channel_state == CHANNEL_STATE_CONNECT
&& relation->rx_state != NOTIFY_STATE_HOLD && relation->rx_state != NOTIFY_STATE_HOLD
&& relation->rx_state != NOTIFY_STATE_SUSPEND) && relation->rx_state != NOTIFY_STATE_SUSPEND
&& relations>1 // no conf with on party
&& allmISDN) // no conf if any member is not mISDN
{ {
message = message_create(c_serial, relation->epoint_id, CALL_TO_EPOINT, MESSAGE_mISDNSIGNAL); message = message_create(c_serial, relation->epoint_id, CALL_TO_EPOINT, MESSAGE_mISDNSIGNAL);
message->param.mISDNsignal.message = mISDNSIGNAL_CONF; message->param.mISDNsignal.message = mISDNSIGNAL_CONF;
message->param.mISDNsignal.conf = (c_serial<<1) + 1; message->param.mISDNsignal.conf = c_serial<<16 | c_pid;
PDEBUG(DEBUG_CALL, "%s +on+ id: 0x%08x\n", port->p_name, message->param.mISDNsignal.conf); PDEBUG(DEBUG_CALL, "%s +on+ id: 0x%08x\n", port->p_name, message->param.mISDNsignal.conf);
message_put(message); message_put(message);
} else } else
@ -384,41 +394,31 @@ void CallPBX::mixer(void)
PDEBUG(DEBUG_CALL, "%s +off+ id: 0x%08x\n", port->p_name, message->param.mISDNsignal.conf); PDEBUG(DEBUG_CALL, "%s +off+ id: 0x%08x\n", port->p_name, message->param.mISDNsignal.conf);
message_put(message); message_put(message);
} }
relation = relation->next;
} /*
/* we notify all relations about rxdata. */ * request data from endpoint/port if:
relation = c_relation; * - two relations
while(relation) * - any without mISDN
{ * in this case we bridge
*/
message = message_create(c_serial, relation->epoint_id, CALL_TO_EPOINT, MESSAGE_mISDNSIGNAL); message = message_create(c_serial, relation->epoint_id, CALL_TO_EPOINT, MESSAGE_mISDNSIGNAL);
message->param.mISDNsignal.message = mISDNSIGNAL_NODATA; message->param.mISDNsignal.message = mISDNSIGNAL_CALLDATA;
message->param.mISDNsignal.nodata = nodata; message->param.mISDNsignal.calldata = (relnum==2 && !allmISDN);
PDEBUG(DEBUG_CALL, "call %d sets alldata on port %s to %d\n", c_serial, port->p_name, nodata); PDEBUG(DEBUG_CALL, "call %d sets 'calldata' on port %s to %d\n", c_serial, port->p_name, calldata);
message_put(message); message_put(message);
relation = relation->next; relation = relation->next;
} }
/* count relations and states */ /* two people just exchange their states */
relation = c_relation; if (relations==2 && !c_partyline)
numconnect = 0;
relations = 0;
while(relation) /* count audio-connected and active relations */
{
relations ++;
if ((relation->channel_state == CHANNEL_STATE_CONNECT)
&& (relation->rx_state != NOTIFY_STATE_SUSPEND)
&& (relation->rx_state != NOTIFY_STATE_HOLD))
numconnect ++;
relation = relation->next;
}
if (relations==2 && !c_partyline) /* two people just exchange their states */
{ {
relation = c_relation; relation = c_relation;
relation->tx_state = notify_state_change(c_serial, relation->epoint_id, relation->tx_state, relation->next->rx_state); relation->tx_state = notify_state_change(c_serial, relation->epoint_id, relation->tx_state, relation->next->rx_state);
relation->next->tx_state = notify_state_change(c_serial, relation->next->epoint_id, relation->next->tx_state, relation->rx_state); relation->next->tx_state = notify_state_change(c_serial, relation->next->epoint_id, relation->next->tx_state, relation->rx_state);
} else } else
if ((relations==1 || numconnect==1) /*&& !c_partyline*/) /* one member in a call, so we put her on hold */ /* one member in a call, so we put her on hold */
if (relations==1 || numconnect==1)
{ {
relation = c_relation; relation = c_relation;
while(relation) while(relation)
@ -444,52 +444,45 @@ void CallPBX::mixer(void)
} }
} }
/*
/* send audio data to endpoints which do not come from an endpoint connected * bridging is only possible with two connected endpoints
* to an isdn port and do not go to an endpoint which is connected to an
* isdn port. in this case the mixing cannot be done with kernel space
*/ */
void CallPBX::call_mixer(unsigned long epoint_from, struct call_relation *relation_from, union parameter *param) void CallPBX::bridge_data(unsigned long epoint_from, struct call_relation *relation_from, union parameter *param)
{ {
struct call_relation *relation_to; struct call_relation *relation_to;
struct message *message; struct message *message;
/* if we are alone */
if (!c_relation->next)
return;
/* if we are more than two */
if (c_relation->next->next)
return;
/* skip if source endpoint has NOT audio mode CONNECT */ /* skip if source endpoint has NOT audio mode CONNECT */
if (relation_from->channel_state != CHANNEL_STATE_CONNECT) if (relation_from->channel_state != CHANNEL_STATE_CONNECT)
{
return; return;
}
/* loop all endpoints and skip the endpoint where the audio is from /* get destination relation */
* so we do not get a loop (echo)
*/
relation_to = c_relation; relation_to = c_relation;
while(relation_to) if (relation_to == relation_from)
{ {
/* skip source endpoint */ /* oops, we are the first, so destination is: */
if (relation_to->epoint_id == epoint_from)
{
relation_to = relation_to->next;
continue;
}
/* skip if destination endpoint has audio mode HOLD */
if (relation_to->channel_state != CHANNEL_STATE_CONNECT)
{
relation_to = relation_to->next;
continue;
}
/* now we may send our data to the endpoint where it
* will be delivered to the port
*/
//PDEBUG(DEBUG_CALL, "mixing from %d to %d\n", epoint_from, relation_to->epoint_id);
message = message_create(c_serial, relation_to->epoint_id, CALL_TO_EPOINT, MESSAGE_DATA);
memcpy(&message->param, param, sizeof(union parameter));
message_put(message);
relation_to = relation_to->next; relation_to = relation_to->next;
} }
/* skip if destomatopm endpoint has NOT audio mode CONNECT */
if (relation_to->channel_state != CHANNEL_STATE_CONNECT)
return;
/* now we may send our data to the endpoint where it
* will be delivered to the port
*/
//PDEBUG(DEBUG_CALL, "mixing from %d to %d\n", epoint_from, relation_to->epoint_id);
message = message_create(c_serial, relation_to->epoint_id, CALL_TO_EPOINT, MESSAGE_DATA);
memcpy(&message->param, param, sizeof(union parameter));
message_put(message);
} }
@ -527,11 +520,11 @@ void CallPBX::release(unsigned long epoint_id, int hold, int location, int cause
return; return;
} }
/* remove from mixer */ /* remove from bridge */
if (relation->channel_state != CHANNEL_STATE_HOLD) if (relation->channel_state != CHANNEL_STATE_HOLD)
{ {
relation->channel_state = CHANNEL_STATE_HOLD; relation->channel_state = CHANNEL_STATE_HOLD;
c_mixer = 1; /* update mixer flag */ c_updatebridge = 1; /* update bridge flag */
} }
/* detach given interface */ /* detach given interface */
@ -738,7 +731,7 @@ void CallPBX::message_epoint(unsigned long epoint_id, int message_type, union pa
if (relation->channel_state != param->channel) if (relation->channel_state != param->channel)
{ {
relation->channel_state = param->channel; relation->channel_state = param->channel;
c_mixer = 1; /* update mixer flag */ c_updatebridge = 1; /* update bridge flag */
if (options.deb & DEBUG_CALL) if (options.deb & DEBUG_CALL)
callpbx_debug(this, "Call::message_epoint{after setting new channel state}"); callpbx_debug(this, "Call::message_epoint{after setting new channel state}");
} }
@ -758,7 +751,7 @@ void CallPBX::message_epoint(unsigned long epoint_id, int message_type, union pa
if (new_state != relation->rx_state) if (new_state != relation->rx_state)
{ {
relation->rx_state = new_state; relation->rx_state = new_state;
c_mixer = 1; c_updatebridge = 1;
if (options.deb & DEBUG_CALL) if (options.deb & DEBUG_CALL)
callpbx_debug(this, "Call::message_epoint{after setting new rx state}"); callpbx_debug(this, "Call::message_epoint{after setting new rx state}");
} }
@ -782,8 +775,8 @@ void CallPBX::message_epoint(unsigned long epoint_id, int message_type, union pa
/* audio data */ /* audio data */
case MESSAGE_DATA: case MESSAGE_DATA:
/* now send audio data to all endpoints connected */ /* now send audio data to the other endpoint */
call_mixer(epoint_id, relation, param); bridge_data(epoint_id, relation, param);
return; return;
} }
@ -795,7 +788,7 @@ void CallPBX::message_epoint(unsigned long epoint_id, int message_type, union pa
message = message_create(c_serial, epoint_id, CALL_TO_EPOINT, MESSAGE_CONNECT); message = message_create(c_serial, epoint_id, CALL_TO_EPOINT, MESSAGE_CONNECT);
message->param.setup.partyline = c_partyline; message->param.setup.partyline = c_partyline;
message_put(message); message_put(message);
c_mixer = 1; /* update mixer flag */ c_updatebridge = 1; /* update bridge flag */
} }
if (c_partyline) if (c_partyline)
{ {
@ -807,7 +800,7 @@ void CallPBX::message_epoint(unsigned long epoint_id, int message_type, union pa
message->param.disconnectinfo.cause = CAUSE_NORMAL; message->param.disconnectinfo.cause = CAUSE_NORMAL;
message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL; message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
message_put(message); message_put(message);
// c_mixer = 1; /* update mixer flag */ // c_updatebridge = 1; /* update bridge flag */
return; return;
} }
} }
@ -880,11 +873,11 @@ int CallPBX::handler(void)
// int i, j; // int i, j;
// char *p; // char *p;
/* the mixer must be updated */ /* the bridge must be updated */
if (c_mixer) if (c_updatebridge)
{ {
mixer(); bridge();
c_mixer = 0; c_updatebridge = 0;
return(1); return(1);
} }
@ -988,6 +981,6 @@ int CallPBX::out_setup(unsigned long epoint_id, int message_type, union paramete
todo: beim release von einem relation_type_setup muss der cause gesammelt werden, bis keine weitere setup-relation mehr existiert todo: beim release von einem relation_type_setup muss der cause gesammelt werden, bis keine weitere setup-relation mehr existiert
beim letzten den collected cause senden beim letzten den collected cause senden
mixer kann ruhig loslegen, das aber dokumentieren bridge kann ruhig loslegen, das aber dokumentieren
mixer überdenken: wer sendet, welche töne verfügbar sind, u.s.w bridge überdenken: wer sendet, welche töne verfügbar sind, u.s.w

View File

@ -63,13 +63,13 @@ class CallPBX : public Call
char c_dialed[1024]; /* dial string of (all) number(s) */ char c_dialed[1024]; /* dial string of (all) number(s) */
char c_todial[32]; /* overlap dialing (part not signalled yet) */ char c_todial[32]; /* overlap dialing (part not signalled yet) */
int c_mixer; /* mixer must be updated */ int c_updatebridge; /* bridge must be updated */
struct call_relation *c_relation; /* list of endpoints that are related to the call */ struct call_relation *c_relation; /* list of endpoints that are related to the call */
int c_partyline; /* if set, call is conference room */ int c_partyline; /* if set, call is conference room */
void mixer(void); void bridge(void);
void call_mixer(unsigned long epoint_from, struct call_relation *relation_from, union parameter *param); void bridge_data(unsigned long epoint_from, struct call_relation *relation_from, union parameter *param);
void remove_relation(struct call_relation *relation); void remove_relation(struct call_relation *relation);
struct call_relation *add_relation(void); struct call_relation *add_relation(void);
int out_setup(unsigned long epoint_id, int message, union parameter *param, char *newnumber); int out_setup(unsigned long epoint_id, int message, union parameter *param, char *newnumber);

View File

@ -459,6 +459,7 @@ void Pdss1::setup_ind(unsigned long prim, unsigned long dinfo, void *data)
break; break;
} }
p_callerinfo.isdn_port = p_m_portnum; p_callerinfo.isdn_port = p_m_portnum;
SCPY(p_callerinfo.interface, p_m_mISDNport->ifport->interface->name);
/* dialing information */ /* dialing information */
dec_ie_called_pn(setup->CALLED_PN, (Q931_info_t *)((unsigned long)data+headerlen), &type, &plan, (unsigned char *)p_dialinginfo.number, sizeof(p_dialinginfo.number)); dec_ie_called_pn(setup->CALLED_PN, (Q931_info_t *)((unsigned long)data+headerlen), &type, &plan, (unsigned char *)p_dialinginfo.number, sizeof(p_dialinginfo.number));
dec_ie_keypad(setup->KEYPAD, (Q931_info_t *)((unsigned long)data+headerlen), (unsigned char *)keypad, sizeof(keypad)); dec_ie_keypad(setup->KEYPAD, (Q931_info_t *)((unsigned long)data+headerlen), (unsigned char *)keypad, sizeof(keypad));
@ -844,8 +845,6 @@ void Pdss1::setup_ind(unsigned long prim, unsigned long dinfo, void *data)
message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_SETUP); message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_SETUP);
message->param.setup.isdn_port = p_m_portnum; message->param.setup.isdn_port = p_m_portnum;
message->param.setup.port_type = p_type; message->param.setup.port_type = p_type;
p_callerinfo.isdn_port = p_m_portnum;
SCPY(p_callerinfo.interface, p_m_mISDNport->ifport->interface->name);;
memcpy(&message->param.setup.dialinginfo, &p_dialinginfo, sizeof(struct dialing_info)); memcpy(&message->param.setup.dialinginfo, &p_dialinginfo, sizeof(struct dialing_info));
memcpy(&message->param.setup.callerinfo, &p_callerinfo, sizeof(struct caller_info)); memcpy(&message->param.setup.callerinfo, &p_callerinfo, sizeof(struct caller_info));
memcpy(&message->param.setup.redirinfo, &p_redirinfo, sizeof(struct redir_info)); memcpy(&message->param.setup.redirinfo, &p_redirinfo, sizeof(struct redir_info));
@ -1162,6 +1161,7 @@ void Pdss1::connect_ind(unsigned long prim, unsigned long dinfo, void *data)
break; break;
} }
p_connectinfo.isdn_port = p_m_portnum; p_connectinfo.isdn_port = p_m_portnum;
SCPY(p_connectingo.interface, p_m_mISDNport->ifport->interface->name);
#ifdef CENTREX #ifdef CENTREX
/* te-mode: CONP (connected name identification presentation) */ /* te-mode: CONP (connected name identification presentation) */
if (!p_m_d_ntmode) if (!p_m_d_ntmode)
@ -2100,6 +2100,11 @@ void Pdss1::new_state(int state)
*/ */
int Pdss1::handler(void) int Pdss1::handler(void)
{ {
int ret;
if ((ret = Port::handler()))
return(ret);
/* handle destruction */ /* handle destruction */
if (p_m_delete && p_m_d_l3id==0) if (p_m_delete && p_m_d_l3id==0)
{ {
@ -2108,7 +2113,7 @@ int Pdss1::handler(void)
return(-1); return(-1);
} }
return(PmISDN::handler()); return(0);
} }

View File

@ -713,24 +713,6 @@ int read_extension(struct extension *ext, char *number)
PDEBUG(DEBUG_CONFIG, "given display_int param unknown: %s\n", param); PDEBUG(DEBUG_CONFIG, "given display_int param unknown: %s\n", param);
} }
} else } else
if (!strcmp(option,"display_voip"))
{
i=0;
while(ext_yesno[i])
{
if (!strcasecmp(param,ext_yesno[i]))
break;
i++;
}
if (ext_yesno[i])
{
ext->display_voip = i;
PDEBUG(DEBUG_CONFIG, "display voip %s\n", ext_yesno[i]);
} else
{
PDEBUG(DEBUG_CONFIG, "given display_voip param unknown: %s\n", param);
}
} else
if (!strcmp(option,"display_fake")) if (!strcmp(option,"display_fake"))
{ {
i=0; i=0;
@ -1293,10 +1275,6 @@ int write_extension(struct extension *ext, char *number)
fprintf(fp,"# example: \"200 (int)\"\n"); fprintf(fp,"# example: \"200 (int)\"\n");
fprintf(fp,"display_int %s\n\n",(ext->display_int)?"yes":"no"); fprintf(fp,"display_int %s\n\n",(ext->display_int)?"yes":"no");
fprintf(fp,"# Display H323 caller ids using display override (yes or no)\n");
fprintf(fp,"# example: \"15551212 jolly@192.168.0.3\"\n");
fprintf(fp,"display_voip %s\n\n",(ext->display_voip)?"yes":"no");
fprintf(fp,"# Display if calls are anonymous using display override (yes or no)\n"); fprintf(fp,"# Display if calls are anonymous using display override (yes or no)\n");
fprintf(fp,"# This makes only sense if the anon-ignore feature is enabled.\n"); fprintf(fp,"# This makes only sense if the anon-ignore feature is enabled.\n");
fprintf(fp,"# example: \"15551212 anon\"\n"); fprintf(fp,"# example: \"15551212 anon\"\n");

View File

@ -510,6 +510,8 @@ static int inter_screen(struct interface_screen **ifscreenp, struct interface *i
memuse++; memuse++;
memset(ifscreen, 0, sizeof(struct interface_screen)); memset(ifscreen, 0, sizeof(struct interface_screen));
#warning handle unchanged as unchanged!! #warning handle unchanged as unchanged!!
ifscreen->match_type = -1; /* unchecked */
ifscreen->match_present = -1; /* unchecked */
ifscreen->result_type = -1; /* unchanged */ ifscreen->result_type = -1; /* unchanged */
ifscreen->result_present = -1; /* unchanged */ ifscreen->result_present = -1; /* unchanged */
/* tail port */ /* tail port */
@ -554,7 +556,7 @@ static int inter_screen(struct interface_screen **ifscreenp, struct interface *i
if (ifscreen->match_present != -1) if (ifscreen->match_present != -1)
{ {
presenterror: presenterror:
SPRINT(interface_error, "Error in %s (line %d): presentation type already set earlier.\n", filename, line, parameter); SPRINT(interface_error, "Error in %s (line %d): presentation type already set earlier.\n", filename, line);
return(-1); return(-1);
} }
ifscreen->match_present = INFO_PRESENT_ALLOWED; ifscreen->match_present = INFO_PRESENT_ALLOWED;
@ -566,6 +568,15 @@ static int inter_screen(struct interface_screen **ifscreenp, struct interface *i
ifscreen->match_present = INFO_PRESENT_RESTRICTED; ifscreen->match_present = INFO_PRESENT_RESTRICTED;
} else { } else {
SCPY(ifscreen->match, el); SCPY(ifscreen->match, el);
/* check for % at the end */
if (strchr(el, '%'))
{
if (strchr(el, '%') != el+len(el)-1)
{
SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
return(-1);
}
}
break; break;
} }
} }
@ -616,6 +627,15 @@ static int inter_screen(struct interface_screen **ifscreenp, struct interface *i
ifscreen->result_present = INFO_PRESENT_RESTRICTED; ifscreen->result_present = INFO_PRESENT_RESTRICTED;
} else { } else {
SCPY(ifscreen->result, el); SCPY(ifscreen->result, el);
/* check for % at the end */
if (strchr(el, '%'))
{
if (strchr(el, '%') != el+len(el)-1)
{
SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
return(-1);
}
}
break; break;
} }
} }
@ -716,10 +736,13 @@ struct interface_param interface_param[] = {
"Adds an entry for outgoing calls to the caller ID screen list.\n" "Adds an entry for outgoing calls to the caller ID screen list.\n"
"See 'screen-in' for help."}, "See 'screen-in' for help."},
#if 0
#warning todo: filter, also in the PmISDN object
{"filter", &inter_filter, "<filter> [parameters]", {"filter", &inter_filter, "<filter> [parameters]",
"Adds/appends a filter. Filters are ordered in transmit direction.\n" "Adds/appends a filter. Filters are ordered in transmit direction.\n"
"gain <tx-volume> <rx-volume> - Changes volume (-8 .. 8)\n" "gain <tx-volume> <rx-volume> - Changes volume (-8 .. 8)\n"
"blowfish <key> - Adds encryption. Key must be 4-56 bytes (8-112 hex characters."}, "blowfish <key> - Adds encryption. Key must be 4-56 bytes (8-112 hex characters."},
#endif
{NULL, NULL, NULL, NULL} {NULL, NULL, NULL, NULL}
}; };

View File

@ -60,15 +60,15 @@ PmISDN::PmISDN(int type, mISDNport *mISDNport, char *portname, struct port_setti
p_m_hold = 0; p_m_hold = 0;
p_m_txvol = p_m_rxvol = 0; p_m_txvol = p_m_rxvol = 0;
p_m_conf = 0; p_m_conf = 0;
p_m_txdata = 0;
#warning set delay by routing parameter or interface config #warning set delay by routing parameter or interface config
p_m_delay = 0; p_m_delay = 0;
p_m_echo = 0; p_m_echo = 0;
p_m_tone = 0; p_m_tone = 0;
p_m_rxoff = 0; p_m_rxoff = 0;
p_m_txmix = 0;
p_m_txmix_on = 0;
p_m_nodata = 1; /* may be 1, because call always notifies us */ p_m_nodata = 1; /* may be 1, because call always notifies us */
p_m_dtmf = !options.nodtmf; p_m_dtmf = !options.nodtmf;
sollen wir daraus eine interface-option machen?:
p_m_timeout = 0; p_m_timeout = 0;
p_m_timer = 0; p_m_timer = 0;
#warning denke auch an die andere seite. also das setup sollte dies weitertragen #warning denke auch an die andere seite. also das setup sollte dies weitertragen
@ -205,6 +205,11 @@ static void bchannel_activate(struct mISDNport *mISDNport, int i)
} }
/* configure dsp features */ /* configure dsp features */
if (mISDNport->b_port[i]->p_m_txdata)
{
PDEBUG(DEBUG_BCHANNEL, "during activation, we set txdata to txdata=%d.\n", mISDNport->b_port[i]->p_m_txdata);
ph_control(mISDNport->b_addr[i], (mISDNport->b_port[i]->p_m_txdata)?CMX_TXDATA_ON:CMX_TXDATA_OFF);
}
if (mISDNport->b_port[i]->p_m_delay) if (mISDNport->b_port[i]->p_m_delay)
{ {
PDEBUG(DEBUG_BCHANNEL, "during activation, we set delay to delay=%d.\n", mISDNport->b_port[i]->p_m_delay); PDEBUG(DEBUG_BCHANNEL, "during activation, we set delay to delay=%d.\n", mISDNport->b_port[i]->p_m_delay);
@ -241,11 +246,13 @@ static void bchannel_activate(struct mISDNport *mISDNport, int i)
PDEBUG(DEBUG_BCHANNEL, "during activation, we set rxoff to rxoff=%d.\n", mISDNport->b_port[i]->p_m_rxoff); PDEBUG(DEBUG_BCHANNEL, "during activation, we set rxoff to rxoff=%d.\n", mISDNport->b_port[i]->p_m_rxoff);
ph_control(mISDNport->b_addr[i], CMX_RECEIVE_OFF, 0); ph_control(mISDNport->b_addr[i], CMX_RECEIVE_OFF, 0);
} }
#if 0
if (mISDNport->b_port[i]->p_m_txmix) if (mISDNport->b_port[i]->p_m_txmix)
{ {
PDEBUG(DEBUG_BCHANNEL, "during activation, we set txmix to txmix=%d.\n", mISDNport->b_port[i]->p_m_txmix); PDEBUG(DEBUG_BCHANNEL, "during activation, we set txmix to txmix=%d.\n", mISDNport->b_port[i]->p_m_txmix);
ph_control(mISDNport->b_addr[i], CMX_MIX_ON, 0); ph_control(mISDNport->b_addr[i], CMX_MIX_ON, 0);
} }
#endif
if (mISDNport->b_port[i]->p_m_dtmf) if (mISDNport->b_port[i]->p_m_dtmf)
{ {
PDEBUG(DEBUG_BCHANNEL, "during activation, we set dtmf to dtmf=%d.\n", mISDNport->b_port[i]->p_m_dtmf); PDEBUG(DEBUG_BCHANNEL, "during activation, we set dtmf to dtmf=%d.\n", mISDNport->b_port[i]->p_m_dtmf);
@ -285,6 +292,11 @@ static void bchannel_deactivate(struct mISDNport *mISDNport, int i)
/* reset dsp features */ /* reset dsp features */
if (mISDNport->b_port[i]) if (mISDNport->b_port[i])
{ {
if (mISDNport->b_port[i]->p_m_delay)
{
PDEBUG(DEBUG_BCHANNEL, "during deactivation, we reset txdata from txdata=%d.\n", mISDNport->b_port[i]->p_m_txdata);
ph_control(mISDNport->b_addr[i], CMX_TXDATA_OFF, 0);
}
if (mISDNport->b_port[i]->p_m_delay) if (mISDNport->b_port[i]->p_m_delay)
{ {
PDEBUG(DEBUG_BCHANNEL, "during deactivation, we reset delay from delay=%d.\n", mISDNport->b_port[i]->p_m_delay); PDEBUG(DEBUG_BCHANNEL, "during deactivation, we reset delay from delay=%d.\n", mISDNport->b_port[i]->p_m_delay);
@ -320,11 +332,13 @@ static void bchannel_deactivate(struct mISDNport *mISDNport, int i)
PDEBUG(DEBUG_BCHANNEL, "during deactivation, we reset rxoff from rxoff=%d.\n", mISDNport->b_port[i]->p_m_rxoff); PDEBUG(DEBUG_BCHANNEL, "during deactivation, we reset rxoff from rxoff=%d.\n", mISDNport->b_port[i]->p_m_rxoff);
ph_control(mISDNport->b_addr[i], CMX_RECEIVE_ON, 0); ph_control(mISDNport->b_addr[i], CMX_RECEIVE_ON, 0);
} }
#if 0
if (mISDNport->b_port[i]->p_m_txmix) if (mISDNport->b_port[i]->p_m_txmix)
{ {
PDEBUG(DEBUG_BCHANNEL, "during deactivation, we reset txmix from txmix=%d.\n", mISDNport->b_port[i]->p_m_txmix); PDEBUG(DEBUG_BCHANNEL, "during deactivation, we reset txmix from txmix=%d.\n", mISDNport->b_port[i]->p_m_txmix);
ph_control(mISDNport->b_addr[i], CMX_MIX_OFF, 0); ph_control(mISDNport->b_addr[i], CMX_MIX_OFF, 0);
} }
#endif
if (mISDNport->b_port[i]->p_m_dtmf) if (mISDNport->b_port[i]->p_m_dtmf)
{ {
PDEBUG(DEBUG_BCHANNEL, "during deactivation, we reset dtmf from dtmf=%d.\n", mISDNport->b_port[i]->p_m_dtmf); PDEBUG(DEBUG_BCHANNEL, "during deactivation, we reset dtmf from dtmf=%d.\n", mISDNport->b_port[i]->p_m_dtmf);
@ -641,6 +655,7 @@ void PmISDN::bchannel_receive(iframe_t *frm)
if (newlen>0 && (p_tone_fh>=0 || p_tone_fetched || !p_m_nodata || p_m_crypt_msg_loops)) if (newlen>0 && (p_tone_fh>=0 || p_tone_fetched || !p_m_nodata || p_m_crypt_msg_loops))
{ {
//printf("jolly: sending.... %d %d %d %d %d\n", newlen, p_tone_fh, p_tone_fetched, p_m_nodata, p_m_crypt_msg_loops); //printf("jolly: sending.... %d %d %d %d %d\n", newlen, p_tone_fh, p_tone_fetched, p_m_nodata, p_m_crypt_msg_loops);
#if 0
if (p_m_txmix_on) if (p_m_txmix_on)
{ {
p_m_txmix_on -= newlen; p_m_txmix_on -= newlen;
@ -653,6 +668,7 @@ void PmISDN::bchannel_receive(iframe_t *frm)
ph_control(p_m_b_addr, CMX_MIX_ON, 0); ph_control(p_m_b_addr, CMX_MIX_ON, 0);
} }
} }
#endif
if (p_m_crypt_msg_loops) if (p_m_crypt_msg_loops)
{ {
/* send pending message */ /* send pending message */
@ -667,11 +683,13 @@ void PmISDN::bchannel_receive(iframe_t *frm)
{ {
p_m_crypt_msg_current = 0; p_m_crypt_msg_current = 0;
p_m_crypt_msg_loops--; p_m_crypt_msg_loops--;
#if 0
// we need to disable rxmix some time after sending the loops... // we need to disable rxmix some time after sending the loops...
if (!p_m_crypt_msg_loops && p_m_txmix) if (!p_m_crypt_msg_loops && p_m_txmix)
{ {
p_m_txmix_on = 8000; /* one sec */ p_m_txmix_on = 8000; /* one sec */
} }
#endif
} }
} }
frm->prim = frm->prim & 0xfffffffc | REQUEST; frm->prim = frm->prim & 0xfffffffc | REQUEST;
@ -873,6 +891,16 @@ void PmISDN::message_mISDNsignal(unsigned long epoint_id, int message_id, union
//if (dddebug) PDEBUG(DEBUG_ISDN, "dddebug = %d\n", dddebug->type); //if (dddebug) PDEBUG(DEBUG_ISDN, "dddebug = %d\n", dddebug->type);
break; break;
case mISDNSIGNAL_CALLDATA:
if (p_m_calldata != param->mISDNsignal.calldata)
{
p_m_calldata = param->mISDNsignal.calldata;
PDEBUG(DEBUG_BCHANNEL, "we change to calldata=%d.\n", p_m_calldata);
auch senden
}
break;
#if 0
case mISDNSIGNAL_NODATA: case mISDNSIGNAL_NODATA:
p_m_nodata = param->mISDNsignal.nodata; p_m_nodata = param->mISDNsignal.nodata;
if (p_m_txmix == p_m_nodata) /* txmix != !nodata */ if (p_m_txmix == p_m_nodata) /* txmix != !nodata */
@ -884,6 +912,7 @@ void PmISDN::message_mISDNsignal(unsigned long epoint_id, int message_id, union
ph_control(p_m_b_addr, p_m_txmix?CMX_MIX_ON:CMX_MIX_OFF, 0); ph_control(p_m_b_addr, p_m_txmix?CMX_MIX_ON:CMX_MIX_OFF, 0);
} }
break; break;
#endif
#if 0 #if 0
case mISDNSIGNAL_RXOFF: case mISDNSIGNAL_RXOFF:
@ -963,12 +992,14 @@ void PmISDN::message_crypt(unsigned long epoint_id, int message_id, union parame
} }
p_m_crypt_msg_current = 0; /* reset */ p_m_crypt_msg_current = 0; /* reset */
p_m_crypt_msg_loops = 3; /* enable */ p_m_crypt_msg_loops = 3; /* enable */
#if 0
/* disable txmix, or we get corrupt data due to audio process */ /* disable txmix, or we get corrupt data due to audio process */
if (p_m_txmix) if (p_m_txmix)
{ {
PDEBUG(DEBUG_BCHANNEL, "for sending CR_MESSAGE_REQ, we reset txmix from txmix=%d.\n", p_m_txmix); PDEBUG(DEBUG_BCHANNEL, "for sending CR_MESSAGE_REQ, we reset txmix from txmix=%d.\n", p_m_txmix);
ph_control(p_m_b_addr, CMX_MIX_OFF, 0); ph_control(p_m_b_addr, CMX_MIX_OFF, 0);
} }
#endif
break; break;
default: default:
@ -1017,6 +1048,9 @@ int mISDN_handler(void)
mISDNuser_head_t *hh; mISDNuser_head_t *hh;
int i; int i;
if ((ret = Port::handler()))
return(ret);
/* the que avoids loopbacks when replying to stack after receiving /* the que avoids loopbacks when replying to stack after receiving
* from stack. */ * from stack. */
mISDNport = mISDNport_first; mISDNport = mISDNport_first;

View File

@ -101,8 +101,8 @@ class PmISDN : public Port
int p_m_tone; /* current kernel space tone */ int p_m_tone; /* current kernel space tone */
int p_m_rxoff; /* rx from driver is disabled */ int p_m_rxoff; /* rx from driver is disabled */
int p_m_nodata; /* all parties within a conf are isdn ports, so pure bridging is possible */ int p_m_nodata; /* all parties within a conf are isdn ports, so pure bridging is possible */
int p_m_txmix; /* mix tx with conference */ // int p_m_txmix; /* mix tx with conference */
int p_m_txmix_on; /* delay for turning back on after sending a binary message, must be signed */ // int p_m_txmix_on; /* delay for turning back on after sending a binary message, must be signed */
int p_m_dtmf; /* dtmf decoding is enabled */ int p_m_dtmf; /* dtmf decoding is enabled */
int p_m_crypt; /* encryption is enabled */ int p_m_crypt; /* encryption is enabled */

119
main.c
View File

@ -49,39 +49,6 @@ pthread_mutex_t mutexd; // debug output mutex
pthread_mutex_t mutexl; // log output mutex pthread_mutex_t mutexl; // log output mutex
pthread_mutex_t mutexe; // error output mutex pthread_mutex_t mutexe; // error output mutex
#ifdef H323
PMutex mutex_h323; // mutual exclude threads when using OpenH323
#endif
#ifdef VOIP
class PBXMain : public PProcess
{
PCLASSINFO(PBXMain, PProcess)
public:
PBXMain(void);
~PBXMain(void);
void Main();
};
PCREATE_PROCESS(PBXMain)
PBXMain::PBXMain(void) : PProcess("Jolly", "LinuxPBX", 0, 1, AlphaCode, 1)
{
}
PBXMain::~PBXMain(void)
{
}
#endif
#ifdef H323
H323_ep *h323_ep = NULL;
#endif
#ifdef OPAL
OpalManager *opal_mgr = NULL;
#endif
int memuse = 0; int memuse = 0;
int mmemuse = 0; int mmemuse = 0;
int cmemuse = 0; int cmemuse = 0;
@ -277,15 +244,7 @@ int main(int argc, char *argv[])
GET_NOW(); GET_NOW();
/* show version */ /* show version */
#ifdef OPAL
printf("\n** %s Version %s (with OPAL)\n\n", NAME, VERSION_STRING);
#else
#ifdef H323
printf("\n** %s Version %s (with H323)\n\n", NAME, VERSION_STRING);
#else
printf("\n** %s Version %s\n\n", NAME, VERSION_STRING); printf("\n** %s Version %s\n\n", NAME, VERSION_STRING);
#endif
#endif
/* show options */ /* show options */
if (ARGC <= 1) if (ARGC <= 1)
@ -485,39 +444,6 @@ int main(int argc, char *argv[])
goto free; goto free;
} }
#ifdef OPAL
/* create OPAL manager */
opal_mgr = new PBXManager;
if (!opal_mgr)
{
fprintf(stderr, "Unable to create OPAL manager.\n");
goto free;
}
if (opal_mgr->Initialise())
{
todo thread kreieren...
opal_mgr->Main();
}
#endif
#ifdef H323
// create h323 endpoint and initialize
h323_ep = new H323_ep();
if (!h323_ep)
{
fprintf(stderr, "Unable to create h323 endpoint.\n");
goto free;
}
if (h323_ep->Init() == FALSE)
{
fprintf(stderr, "Unable to init h323 endpoint.\n");
goto free;
}
#endif
/* read interfaces and open ports */ /* read interfaces and open ports */
if (!read_interfaces()) if (!read_interfaces())
{ {
@ -591,10 +517,6 @@ int main(int argc, char *argv[])
while(!quit) while(!quit)
{ {
/* all loops must be counted from the beginning since nodes might get freed during handler */ /* all loops must be counted from the beginning since nodes might get freed during handler */
#ifdef H323
mutex_h323.Wait();
debug_prefix = 0;
#endif
all_idle = 1; all_idle = 1;
/* handle mISDN messages from kernel */ /* handle mISDN messages from kernel */
@ -801,12 +723,6 @@ BUDETECT
GET_NOW(); GET_NOW();
#endif #endif
#ifdef H323
// NOTE: be carefull with this, don't do anything after unlocking except sleeping and locking!
debug_prefix = "h323";
mutex_h323.Signal();
#endif
/* did we do nothing? so we wait to give time to other processes */ /* did we do nothing? so we wait to give time to other processes */
if (all_idle) if (all_idle)
{ {
@ -822,7 +738,6 @@ free:
/* set scheduler & priority /* set scheduler & priority
* we must remove realtimeshed, because h323 may lock during exit
*/ */
if (options.schedule > 1) if (options.schedule > 1)
{ {
@ -840,9 +755,6 @@ free:
} }
/* destroy objects */ /* destroy objects */
#ifdef H323
mutex_h323.Wait();
#endif
debug_prefix = "free"; debug_prefix = "free";
while(port_first) while(port_first)
@ -880,37 +792,6 @@ free:
PDEBUG(DEBUG_MSG, "freed %d pending messages\n", i); PDEBUG(DEBUG_MSG, "freed %d pending messages\n", i);
} }
#ifdef H323
mutex_h323.Signal();
#endif
#ifdef OPAL
/* destroy manager */
if (opal_mgr)
{
todo kill an den main-thread von opal und warten...
if (options.deb & DEBUG_OPAL)
printf("->now deleting opal manager\n");
delete opal_mgr;
if (options.deb & DEBUG_OPAL)
printf("->opal manager deleted\n");
}
#endif
#ifdef H323
/* destroy endpoint */
if (h323_ep)
{
if (options.deb & DEBUG_H323)
printf("->now deleting endpoint\n");
delete h323_ep;
if (options.deb & DEBUG_H323)
printf("->endpoint deleted\n");
}
#endif
/* free tones */ /* free tones */
if (toneset_first) if (toneset_first)
free_tones(); free_tones();

68
main.h
View File

@ -40,8 +40,6 @@ void _printerror(const char *function, int line, const char *fmt, ...);
#define DEBUG_BCHANNEL 0x0008 #define DEBUG_BCHANNEL 0x0008
#define DEBUG_PORT 0x0100 #define DEBUG_PORT 0x0100
#define DEBUG_ISDN 0x0110 #define DEBUG_ISDN 0x0110
#define DEBUG_OPAL 0x0120
#define DEBUG_H323 0x0130
//#define DEBUG_KNOCK 0x0140 //#define DEBUG_KNOCK 0x0140
#define DEBUG_VBOX 0x0180 #define DEBUG_VBOX 0x0180
#define DEBUG_EPOINT 0x0200 #define DEBUG_EPOINT 0x0200
@ -60,31 +58,18 @@ void _printerror(const char *function, int line, const char *fmt, ...);
*/ */
#define DEBUG_LOG 0x7fff #define DEBUG_LOG 0x7fff
/* audio buffer for mixer and recording. /*
* all partys within a call (most time two endpoints) write audio data to the buffer. this is used because * transmit interval for tones and announcements (or samples of all kind)
* the buffer experience jitter. if the buffer is too small, jitter will cause drops and gaps. *
* if the buffer is too large, the delay is large. 768 is a good value to start with.
*/ */
#ifdef VOIP #define ISDN_TRANSMIT 128
#warning to be removed soon
#endif
#define PORT_BUFFER 768
/* keep this 0 for minimum delay */ /*
#ifdef VOIP * preload transmit buffer to avoid gaps at the beginning due to jitter
#warning to be removed soon * keep this 0 for minimum delay
#endif */
#define ISDN_PRELOAD 0 #define ISDN_PRELOAD 0
/* the jitterlimit specifies the number of samples received too fast, before
* it recognizes a stalling process.
* but should NOT be less 256.
*/
#ifdef VOIP
#warning to be removed soon
#endif
#define ISDN_JITTERLIMIT 512 /* maximum samples received before dropping */
/* give sendmail program. if not inside $PATH, give absolute path here (e.g. "/usr/sbin/sendmail") /* give sendmail program. if not inside $PATH, give absolute path here (e.g. "/usr/sbin/sendmail")
*/ */
#define SENDMAIL "sendmail" #define SENDMAIL "sendmail"
@ -118,28 +103,6 @@ void _printerror(const char *function, int line, const char *fmt, ...);
#define BUDETECT ; #define BUDETECT ;
#endif #endif
#ifdef H323
#define VOIP
#ifdef OPAL
#error It is not allowed to use H323 and OPAL. Please disable H323, because it is included in OPAL.
#endif
#endif
#ifdef OPAL
#define VOIP
#endif
#ifdef H323INCLUDE
#define NO_VIDEO_CAPTURE
//#include <vector>
//#include <string>
#include <ptlib.h>
#include <h225.h>
#include <h323.h>
#include <h323pdu.h>
#include <h323caps.h>
#include <q931.h>
#endif
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
@ -158,7 +121,6 @@ extern "C" {
#include "save.h" #include "save.h"
#include "options.h" #include "options.h"
#include "interface.h" #include "interface.h"
#include "h323conf.h"
#include "extension.h" #include "extension.h"
#include "message.h" #include "message.h"
#include "endpoint.h" #include "endpoint.h"
@ -168,12 +130,6 @@ extern "C" {
#include "port.h" #include "port.h"
#include "mISDN.h" #include "mISDN.h"
#include "dss1.h" #include "dss1.h"
#ifdef H323
#include "h323.h"
#endif
#ifdef OPAL
#include "opal.h"
#endif
#include "vbox.h" #include "vbox.h"
#include "call.h" #include "call.h"
#include "callpbx.h" #include "callpbx.h"
@ -191,12 +147,4 @@ extern struct timeval now_tv;
extern struct timezone now_tz; extern struct timezone now_tz;
#ifdef H323INCLUDE
#include "h323_ep.h"
#include "h323_con.h"
#include "h323_chan.h"
extern PMutex mutex_h323; // mutual exclude for synchroniszing threads
extern H323_ep *h323_ep;
#endif

View File

@ -19,10 +19,6 @@ MESSAGES
struct message *message_first = NULL; struct message *message_first = NULL;
struct message **messagepointer_end = &message_first; struct message **messagepointer_end = &message_first;
//#ifdef H323
//PMutex mutex_message;
//#endif
/* creates a new message with the given attributes. the message must be filled then. after filling, the message_put must be called */ /* creates a new message with the given attributes. the message must be filled then. after filling, the message_put must be called */
struct message *message_create(int id_from, int id_to, int flow, int type) struct message *message_create(int id_from, int id_to, int flow, int type)
{ {
@ -60,11 +56,6 @@ struct message *message_create(int id_from, int id_to, int flow, int type)
/* attaches a message to the end of the message chain */ /* attaches a message to the end of the message chain */
void message_put(struct message *message) void message_put(struct message *message)
{ {
/* the mutex prevents from creating two messages at a time (h323 thread and main thread). */
//#ifdef H323
// mutex_message.Wait();
//#endif
if (message->id_to == 0) if (message->id_to == 0)
{ {
PDEBUG(DEBUG_MSG, "message %s not written, because destination is 0.\n", messages_txt[message->type]); PDEBUG(DEBUG_MSG, "message %s not written, because destination is 0.\n", messages_txt[message->type]);
@ -77,10 +68,6 @@ void message_put(struct message *message)
*messagepointer_end = message; *messagepointer_end = message;
messagepointer_end = &(message->next); messagepointer_end = &(message->next);
//#ifdef H323
// mutex_message.Signal();
//#endif
} }
@ -89,16 +76,8 @@ struct message *message_get(void)
{ {
struct message *message; struct message *message;
/* the mutex prevents from getting a message while creating a messages at a time (h323 thread and main thread). */
//#ifdef H323
// mutex_message.Wait();
//#endif
if (!message_first) if (!message_first)
{ {
//#ifdef H323
// mutex_message.Signal();
//#endif
return(0); return(0);
} }
@ -107,10 +86,6 @@ struct message *message_get(void)
if (!message_first) if (!message_first)
messagepointer_end = &message_first; messagepointer_end = &message_first;
//#ifdef H323
// mutex_message.Signal();
//#endif
if ((options.deb&DEBUG_MSG) && message->type != MESSAGE_DATA) if ((options.deb&DEBUG_MSG) && message->type != MESSAGE_DATA)
PDEBUG(DEBUG_MSG, "message %s reading from %ld to %ld (memory %x)\n", messages_txt[message->type], message->id_from, message->id_to, message); PDEBUG(DEBUG_MSG, "message %s reading from %ld to %ld (memory %x)\n", messages_txt[message->type], message->id_from, message->id_to, message);

View File

@ -120,7 +120,7 @@ enum { /* diversion types */
enum { /* isdnsignal */ enum { /* isdnsignal */
mISDNSIGNAL_VOLUME, mISDNSIGNAL_VOLUME,
mISDNSIGNAL_CONF, mISDNSIGNAL_CONF,
mISDNSIGNAL_NODATA, /* no data required */ mISDNSIGNAL_CALLDATA, /* data required by call instance */
mISDNSIGNAL_ECHO, mISDNSIGNAL_ECHO,
}; };
@ -151,7 +151,7 @@ struct dialing_info {
struct connect_info { struct connect_info {
char id[32]; /* id of caller (user number) */ char id[32]; /* id of caller (user number) */
char voip[64]; /* URI of voip (or gateway) */ char voip[64]; /* URI of voip (or gateway) */
char intern[32]; /* internal id */ char extension[32]; /* internal id */
char name[16]; char name[16];
int isdn_port; /* internal/external port (if call is isdn) */ int isdn_port; /* internal/external port (if call is isdn) */
char interfaces[128]; /* interfaces for extenal calls */ char interfaces[128]; /* interfaces for extenal calls */
@ -241,7 +241,6 @@ struct park_info {
struct param_data { struct param_data {
unsigned char data[512]; /* audio/hdlc data */ unsigned char data[512]; /* audio/hdlc data */
int len; /* audio/hdlc data */ int len; /* audio/hdlc data */
int compressed; /* 0 for law-data, 1 for 16-bit data */
unsigned long port_id; /* to identify the source of this data */ unsigned long port_id; /* to identify the source of this data */
int port_type; /* type of the source's port */ int port_type; /* type of the source's port */
}; };
@ -266,7 +265,7 @@ struct param_mISDNsignal {
int rxvol; int rxvol;
int txvol; int txvol;
int conf; int conf;
int nodata; int calldata;
int tone; int tone;
int echo; int echo;
}; };

171
options.c
View File

@ -31,12 +31,6 @@ struct options options = {
"tones_american", /* directory of tones */ "tones_american", /* directory of tones */
"", /* directories of tones to fetch */ "", /* directories of tones to fetch */
"extensions", /* directory of extensions */ "extensions", /* directory of extensions */
"", /* h323 endpoint name */
0, /* h323 ringconnect */
0,4, 0,2, 0, 0, 0, 0,4, 0,4, 0,64, /* h323 codecs to use */
0,"",1720, /* allow incoming h323 calls */
0,"", /* register with h323 gatekeeper */
5060, 5, /* SIP port, maxqueue */
0, /* dtmf detection on */ 0, /* dtmf detection on */
"", /* dummy caller id */ "", /* dummy caller id */
0, /* use tones by dsp.o */ 0, /* use tones by dsp.o */
@ -57,9 +51,6 @@ int read_options(void)
char param[256]; char param[256];
unsigned int line,i; unsigned int line,i;
char buffer[256]; char buffer[256];
#ifdef H323
int codecpri = 0;
#endif
SPRINT(filename, "%s/options.conf", INSTALL_DATA); SPRINT(filename, "%s/options.conf", INSTALL_DATA);
@ -189,168 +180,6 @@ int read_options(void)
PDEBUG(DEBUG_CONFIG, "isdn audio type: ulaw\n"); PDEBUG(DEBUG_CONFIG, "isdn audio type: ulaw\n");
} else } else
if (!strcmp(option,"h323_name"))
{
#ifdef H323
SCPY(options.h323_name, param);
PDEBUG(DEBUG_CONFIG, "H323 endpoint name: '%s'\n", param);
#endif
} else
if (!strcmp(option,"h323_ringconnect"))
{
#ifdef H323
options.h323_ringconnect = 1;
PDEBUG(DEBUG_CONFIG, "H323 ringconnect: enabled\n");
#endif
} else
if (!strcmp(option,"h323_gsm"))
{
#ifdef H323
codecpri ++;
options.h323_gsm_pri = codecpri;
options.h323_gsm_opt = atoi(param);
if (atoi(param)<1 && atoi(param)>7)
{
PERROR_RUNTIME("Error in %s (line %d): parameter for option %s must be in range 1..7.\n",filename,line,option);
goto error;
}
PDEBUG(DEBUG_CONFIG, "H323 codec to use: GSM, MicrosoftGSM priority %d\n", codecpri);
#endif
} else
if (!strcmp(option,"h323_g726"))
{
#ifdef H323
codecpri ++;
options.h323_g726_pri = codecpri;
options.h323_g726_opt = atoi(param);
if (atoi(param)<2 && atoi(param)>5)
{
PERROR_RUNTIME("Error in %s (line %d): parameter for option %s must be in range 2..5.\n",filename,line,option);
goto error;
}
PDEBUG(DEBUG_CONFIG, "H323 codec to use: G726 priority %d\n", codecpri);
#endif
} else
if (!strcmp(option,"h323_g7231"))
{
#ifdef H323
codecpri ++;
options.h323_g7231_pri = codecpri;
PDEBUG(DEBUG_CONFIG, "H323 codec to use: G7231 priority %d\n", codecpri);
#endif
} else
if (!strcmp(option,"h323_g729a"))
{
#ifdef H323
codecpri ++;
options.h323_g729a_pri = codecpri;
PDEBUG(DEBUG_CONFIG, "H323 codec to use: G729A priority %d\n", codecpri);
#endif
} else
if (!strcmp(option,"h323_lpc10"))
{
#ifdef H323
codecpri ++;
options.h323_lpc10_pri = codecpri;
PDEBUG(DEBUG_CONFIG, "H323 codec to use: LPC-10 priority %d\n", codecpri);
#endif
} else
if (!strcmp(option,"h323_speex"))
{
#ifdef H323
codecpri ++;
options.h323_speex_pri = codecpri;
options.h323_speex_opt = atoi(param);
if (atoi(param)<2 && atoi(param)>6)
{
PERROR_RUNTIME("Error in %s (line %d): parameter for option %s must be in range 2..6.\n",filename,line,option);
goto error;
}
PDEBUG(DEBUG_CONFIG, "H323 codec to use: Speex priority %d\n", codecpri);
#endif
} else
if (!strcmp(option,"h323_xspeex"))
{
#ifdef H323
codecpri ++;
options.h323_xspeex_pri = codecpri;
options.h323_xspeex_opt = atoi(param);
if (atoi(param)<2 && atoi(param)>6)
{
PERROR_RUNTIME("Error in %s (line %d): parameter for option %s must be in range 2..6.\n",filename,line,option);
goto error;
}
PDEBUG(DEBUG_CONFIG, "H323 codec to use: XiphSpeex priority %d\n", codecpri);
#endif
} else
if (!strcmp(option,"h323_law"))
{
#ifdef H323
codecpri ++;
options.h323_law_pri = codecpri;
options.h323_law_opt = atoi(param);
if (atoi(param)<10 && atoi(param)>240)
{
PERROR_RUNTIME("Error in %s (line %d): parameter for option %s must be in range 10..240.\n",filename,line,option);
goto error;
}
PDEBUG(DEBUG_CONFIG, "H323 codec to use: Alaw, muLaw priority %d\n", codecpri);
#endif
} else
if (!strcmp(option,"h323_icall"))
{
#ifdef H323
options.h323_icall = 1;
SCPY(options.h323_icall_prefix, param);
PDEBUG(DEBUG_CONFIG, "process incoming H323 call with prefix '%s'\n", param);
#endif
} else
if (!strcmp(option,"h323_port"))
{
#ifdef H323
options.h323_port = atoi(param);
PDEBUG(DEBUG_CONFIG, "use port for incoming H323 calls: %d\n", atoi(param));
#endif
} else
if (!strcmp(option,"sip_port"))
{
#ifdef SIP
options.sip_port = atoi(param);
PDEBUG(DEBUG_CONFIG, "use port for incoming SIP calls: %d\n", atoi(param));
#endif
} else
if (!strcmp(option,"sip_maxqueue"))
{
#ifdef SIP
options.sip_maxqueue = atoi(param);
PDEBUG(DEBUG_CONFIG, "number of simultanious incoming sockets for SIP calls: %d\n", atoi(param));
#endif
} else
if (!strcmp(option,"h323_gatekeeper"))
{
#ifdef H323
options.h323_gatekeeper = 1;
if (param[0])
{
SCPY(options.h323_gatekeeper_host, param);
}
PDEBUG(DEBUG_CONFIG, "register with H323 gatekeeper (%s)\n", (param[0])?param:"automatically");
#endif
} else
if (!strcmp(option,"tones_dir")) if (!strcmp(option,"tones_dir"))
{ {
if (param[0]==0) if (param[0]==0)

View File

@ -22,28 +22,6 @@ struct options {
char tones_dir[64]; /* directory of all tones/patterns */ char tones_dir[64]; /* directory of all tones/patterns */
char fetch_tones[256]; /* directories of tones to fetch */ char fetch_tones[256]; /* directories of tones to fetch */
char extensions_dir[64]; /* directory of extensions */ char extensions_dir[64]; /* directory of extensions */
char h323_name[128]; /* the name of h323 endpoint */
int h323_ringconnect; /* connected when ringing */
int h323_gsm_pri; /* priority to use of GSM codec (0 == don't use) */
int h323_gsm_opt;
int h323_g726_pri; /* priority to use of G726 codec (0 == don't use) */
int h323_g726_opt;
int h323_g7231_pri; /* priority to use of G7231 codec (0 == don't use) */
int h323_g729a_pri; /* priority to use of G729a codec (0 == don't use) */
int h323_lpc10_pri; /* priority to use of lpc-10 codec (0 == don't use) */
int h323_speex_pri; /* priority to use of speex codec (0 == don't use) */
int h323_speex_opt;
int h323_xspeex_pri; /* priority to use of xspeex codec (0 == don't use) */
int h323_xspeex_opt;
int h323_law_pri; /* priority to use of law codec (0 == don't use) */
int h323_law_opt;
int h323_icall; /* allow incoming h323 calls */
char h323_icall_prefix[32]; /* the prefix */
int h323_port; /* port for incoming calls */
int h323_gatekeeper; /* register with h323 gatekeeper */
char h323_gatekeeper_host[128];/* the gatekeeper host */
int sip_port;
int sip_maxqueue;
int nodtmf; /* use dtmf detection */ int nodtmf; /* use dtmf detection */
char dummyid[32]; /* caller id for external calls if not available */ char dummyid[32]; /* caller id for external calls if not available */
int dsptones; /* tones will be generated via dsp.o 1=american 2=ger */ int dsptones; /* tones will be generated via dsp.o 1=american 2=ger */

1113
port.cpp

File diff suppressed because it is too large Load Diff

16
port.h
View File

@ -24,12 +24,6 @@
/* te-mode */ /* te-mode */
#define PORT_TYPE_DSS1_TE_IN 0x0113 #define PORT_TYPE_DSS1_TE_IN 0x0113
#define PORT_TYPE_DSS1_TE_OUT 0x0114 #define PORT_TYPE_DSS1_TE_OUT 0x0114
/* sip */
#define PORT_TYPE_SIP_IN 0x0121
#define PORT_TYPE_SIP_OUT 0x0122
/* h323 */
#define PORT_TYPE_H323_IN 0x0211
#define PORT_TYPE_H323_OUT 0x0212
/* answering machine */ /* answering machine */
#define PORT_TYPE_VBOX_OUT 0x0311 #define PORT_TYPE_VBOX_OUT 0x0311
@ -172,16 +166,6 @@ class Port
void set_vbox_play(char *name, int offset); /* sample of answ. */ void set_vbox_play(char *name, int offset); /* sample of answ. */
void set_vbox_speed(int speed); /* speed of answ. */ void set_vbox_speed(int speed); /* speed of answ. */
/* user space mixer buffer */
signed long p_mixer_buffer[PORT_BUFFER]; /* mixer buffer */
signed long p_record_buffer[PORT_BUFFER]; /* record buffer */
signed long p_stereo_buffer[PORT_BUFFER]; /* record buffer for stereo (user only) */
struct mixer_relation *p_mixer_rel; /* list of mixer relations */
int p_mixer_readp; /* read pointer in buffer */
/* methods */
void mixer(union parameter *param);
/* identification */ /* identification */
unsigned long p_serial; /* serial unique id of port */ unsigned long p_serial; /* serial unique id of port */
char p_name[128]; /* name of port or token (h323) */ char p_name[128]; /* name of port or token (h323) */

37
route.c
View File

@ -20,16 +20,10 @@ struct route_ruleset *ruleset_first; /* first entry */
struct route_ruleset *ruleset_main; /* pointer to main ruleset */ struct route_ruleset *ruleset_main; /* pointer to main ruleset */
struct cond_defs cond_defs[] = { struct cond_defs cond_defs[] = {
#ifdef PBX
{ "extern", MATCH_EXTERN, COND_TYPE_NULL, { "extern", MATCH_EXTERN, COND_TYPE_NULL,
"extern", "Matches if call is from external port."}, "extern", "Matches if call is from external port (no extension)."},
{ "intern", MATCH_INTERN, COND_TYPE_NULL, { "intern", MATCH_INTERN,COND_TYPE_NULL,
"intern", "Matches if call is from internal port."}, "intern", "Matches if call is from an extension."},
#endif
{ "h323", MATCH_H323, COND_TYPE_NULL,
"h323", "Matches if call is received via H.323."},
// { "ip", MATCH_IP, COND_TYPE_IP,
// "ip=<ip>[-<ip>|/<mask>][,...]", "Matches if caller matches given source IP address(es) / range(s) / block(s)."},
{ "port", MATCH_PORT, COND_TYPE_INTEGER, { "port", MATCH_PORT, COND_TYPE_INTEGER,
"port=<number>[-<number>][,...]", "Matches if call is received from given port(s). NOT INTERFACE!"}, "port=<number>[-<number>][,...]", "Matches if call is received from given port(s). NOT INTERFACE!"},
{ "interface", MATCH_INTERFACE,COND_TYPE_STRING, { "interface", MATCH_INTERFACE,COND_TYPE_STRING,
@ -111,14 +105,12 @@ struct param_defs param_defs[] = {
{ PARAM_CONNECT, { PARAM_CONNECT,
"connect", PARAM_TYPE_NULL, "connect", PARAM_TYPE_NULL,
"connect", "Will complete the call before processing the action. Audio path for external calls will be established."}, "connect", "Will complete the call before processing the action. Audio path for external calls will be established."},
#ifdef PBX
{ PARAM_EXTENSION, { PARAM_EXTENSION,
"extension", PARAM_TYPE_STRING, "extension", PARAM_TYPE_STRING,
"extension=<digits>", "Give extension name (digits) to relate this action to."}, "extension=<digits>", "Give extension name (digits) to relate this action to."},
{ PARAM_EXTENSIONS, { PARAM_EXTENSIONS,
"extensions", PARAM_TYPE_STRING, "extensions", PARAM_TYPE_STRING,
"extensions=<extension>[,<extension>[,...]]", "One or more extensions may be given."}, "extensions=<extension>[,<extension>[,...]]", "One or more extensions may be given."},
#endif
{ PARAM_PREFIX, { PARAM_PREFIX,
"prefix", PARAM_TYPE_STRING, "prefix", PARAM_TYPE_STRING,
"prefix=<digits>", "Add prefix in front of the dialed number."}, "prefix=<digits>", "Add prefix in front of the dialed number."},
@ -170,11 +162,9 @@ struct param_defs param_defs[] = {
{ PARAM_SAMPLE, { PARAM_SAMPLE,
"sample", PARAM_TYPE_STRING, "sample", PARAM_TYPE_STRING,
"sample=<file prefix>", "Filename of sample (current tone's dir) or full path to sample. ('.wav'/'.wave'/'.isdn' is added automatically."}, "sample=<file prefix>", "Filename of sample (current tone's dir) or full path to sample. ('.wav'/'.wave'/'.isdn' is added automatically."},
#ifdef PBX
{ PARAM_ANNOUNCEMENT, { PARAM_ANNOUNCEMENT,
"announcement",PARAM_TYPE_STRING, "announcement",PARAM_TYPE_STRING,
"announcement=<file prefix>", "Filename of announcement (inside vbox recording dir) or full path to sample. ('.wav'/'.wave'/'.isdn' is added automatically."}, "announcement=<file prefix>", "Filename of announcement (inside vbox recording dir) or full path to sample. ('.wav'/'.wave'/'.isdn' is added automatically."},
#endif
{ PARAM_RULESET, { PARAM_RULESET,
"ruleset", PARAM_TYPE_STRING, "ruleset", PARAM_TYPE_STRING,
"ruleset=<name>", "Ruleset to go to."}, "ruleset=<name>", "Ruleset to go to."},
@ -229,11 +219,9 @@ struct param_defs param_defs[] = {
{ PARAM_TIMEOUT, { PARAM_TIMEOUT,
"timeout", PARAM_TYPE_INTEGER, "timeout", PARAM_TYPE_INTEGER,
"timeout=<seconds>", "Timeout before continue with next action."}, "timeout=<seconds>", "Timeout before continue with next action."},
#ifdef PBX
{ PARAM_NOPASSWORD, { PARAM_NOPASSWORD,
"nopassword", PARAM_TYPE_NULL, "nopassword", PARAM_TYPE_NULL,
"nopassword", "Don't ask for password. Be sure to authenticate right via real caller ID."}, "nopassword", "Don't ask for password. Be sure to authenticate right via real caller ID."},
#endif
{ 0, NULL, 0, NULL, NULL} { 0, NULL, 0, NULL, NULL}
}; };
@ -250,10 +238,6 @@ struct action_defs action_defs[] = {
"outdial", &EndpointAppPBX::action_init_call, &EndpointAppPBX::action_dialing_external, &EndpointAppPBX::action_hangup_call, "outdial", &EndpointAppPBX::action_init_call, &EndpointAppPBX::action_dialing_external, &EndpointAppPBX::action_hangup_call,
PARAM_CONNECT | PARAM_PREFIX | PARAM_COMPLETE | PARAM_TYPE | PARAM_CAPA | PARAM_BMODE | PARAM_INFO1 | PARAM_HLC | PARAM_EXTHLC | PARAM_PRESENT | PARAM_INTERFACES | PARAM_CALLERID | PARAM_CALLERIDTYPE | PARAM_TIMEOUT, PARAM_CONNECT | PARAM_PREFIX | PARAM_COMPLETE | PARAM_TYPE | PARAM_CAPA | PARAM_BMODE | PARAM_INFO1 | PARAM_HLC | PARAM_EXTHLC | PARAM_PRESENT | PARAM_INTERFACES | PARAM_CALLERID | PARAM_CALLERIDTYPE | PARAM_TIMEOUT,
"Same as 'extern'"}, "Same as 'extern'"},
{ ACTION_H323,
"h323", &EndpointAppPBX::action_init_call, &EndpointAppPBX::action_dialing_h323, &EndpointAppPBX::action_hangup_call,
PARAM_CONNECT | PARAM_PREFIX | PARAM_HOST | PARAM_PORT | PARAM_ADDRESS | PARAM_TIMEOUT,
"Call is routed to H.323 host/gateway."},
{ ACTION_CHAN, { ACTION_CHAN,
"asterisk", &EndpointAppPBX::action_init_chan, &EndpointAppPBX::action_dialing_chan, &EndpointAppPBX::action_hangup_call, "asterisk", &EndpointAppPBX::action_init_chan, &EndpointAppPBX::action_dialing_chan, &EndpointAppPBX::action_hangup_call,
PARAM_CONNECT | PARAM_TIMEOUT, PARAM_CONNECT | PARAM_TIMEOUT,
@ -2038,13 +2022,6 @@ struct route_action *EndpointAppPBX::route(struct route_ruleset *ruleset)
istrue = 1; istrue = 1;
break; break;
case MATCH_H323:
// printf("\n\n\nport-type %x\n\n\n\n", ea_endpoint->ep_portlist->port_type);
if (ea_endpoint->ep_portlist)
if (ea_endpoint->ep_portlist->port_type == PORT_TYPE_H323_IN)
istrue = 1;
break;
case MATCH_PORT: case MATCH_PORT:
if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist)
if ((ea_endpoint->ep_portlist->port_type & PORT_CLASS_mISDN_MASK) != PORT_CLASS_mISDN_DSS1) if ((ea_endpoint->ep_portlist->port_type & PORT_CLASS_mISDN_MASK) != PORT_CLASS_mISDN_DSS1)
@ -2481,14 +2458,6 @@ struct route_action action_internal = {
0, 0,
}; };
struct route_action action_h323 = {
NULL,
NULL,
ACTION_H323,
0,
0,
};
struct route_action action_chan = { struct route_action action_chan = {
NULL, NULL,
NULL, NULL,

68
route.h
View File

@ -36,12 +36,8 @@ enum { /* how to parse text file during startup */
}; };
enum { /* what to check during runtime */ enum { /* what to check during runtime */
#ifdef PBX
MATCH_EXTERN, MATCH_EXTERN,
MATCH_INTERN, MATCH_INTERN,
#endif
MATCH_H323,
// MATCH_IP,
MATCH_PORT, MATCH_PORT,
MATCH_INTERFACE, MATCH_INTERFACE,
MATCH_CALLERID, MATCH_CALLERID,
@ -96,10 +92,8 @@ enum { /* how to parse text file during startup */
#define PARAM_PROCEEDING 1LL #define PARAM_PROCEEDING 1LL
#define PARAM_ALERTING (1LL<<1) #define PARAM_ALERTING (1LL<<1)
#define PARAM_CONNECT (1LL<<2) #define PARAM_CONNECT (1LL<<2)
#ifdef PBX
#define PARAM_EXTENSION (1LL<<3) #define PARAM_EXTENSION (1LL<<3)
#define PARAM_EXTENSIONS (1LL<<4) #define PARAM_EXTENSIONS (1LL<<4)
#endif
#define PARAM_PREFIX (1LL<<5) #define PARAM_PREFIX (1LL<<5)
#define PARAM_CAPA (1LL<<6) #define PARAM_CAPA (1LL<<6)
#define PARAM_BMODE (1LL<<7) #define PARAM_BMODE (1LL<<7)
@ -149,37 +143,36 @@ enum { /* how to parse text file during startup */
#define ACTION_EXTERNAL 0 #define ACTION_EXTERNAL 0
#define ACTION_INTERNAL 1 #define ACTION_INTERNAL 1
#define ACTION_OUTDIAL 2 #define ACTION_OUTDIAL 2
#define ACTION_H323 3 #define ACTION_CHAN 3
#define ACTION_CHAN 4 #define ACTION_VBOX_RECORD 4
#define ACTION_VBOX_RECORD 5 #define ACTION_PARTYLINE 5
#define ACTION_PARTYLINE 6 #define ACTION_LOGIN 6
#define ACTION_LOGIN 7 #define ACTION_CALLERID 7
#define ACTION_CALLERID 8 #define ACTION_CALLERIDNEXT 8
#define ACTION_CALLERIDNEXT 9 #define ACTION_FORWARD 9
#define ACTION_FORWARD 10 #define ACTION_REDIAL 10
#define ACTION_REDIAL 11 #define ACTION_REPLY 11
#define ACTION_REPLY 12 #define ACTION_POWERDIAL 12
#define ACTION_POWERDIAL 13 #define ACTION_CALLBACK 13
#define ACTION_CALLBACK 14 #define ACTION_ABBREV 14
#define ACTION_ABBREV 15 #define ACTION_TEST 15
#define ACTION_TEST 16 #define ACTION_PLAY 16
#define ACTION_PLAY 17 #define ACTION_VBOX_PLAY 17
#define ACTION_VBOX_PLAY 18 #define ACTION_CALCULATOR 18
#define ACTION_CALCULATOR 19 #define ACTION_TIMER 19
#define ACTION_TIMER 20 #define ACTION_GOTO 20
#define ACTION_GOTO 21 #define ACTION_MENU 21
#define ACTION_MENU 22 #define ACTION_DISCONNECT 22
#define ACTION_DISCONNECT 23 #define ACTION_HELP 23
#define ACTION_HELP 24 #define ACTION_DEFLECT 24
#define ACTION_DEFLECT 25 #define ACTION_SETFORWARD 25
#define ACTION_SETFORWARD 26 #define ACTION_EXECUTE 26
#define ACTION_EXECUTE 27 #define ACTION_FILE 27
#define ACTION_FILE 28 #define ACTION_PICK 28
#define ACTION_PICK 29 #define ACTION_PASSWORD 29
#define ACTION_PASSWORD 30 #define ACTION_PASSWORD_WRITE 30
#define ACTION_PASSWORD_WRITE 31 #define ACTION_NOTHING 31
#define ACTION_NOTHING 32 #define ACTION_EFI 32
#define ACTION_EFI 33
struct route_cond { /* an item */ struct route_cond { /* an item */
struct route_cond *next; /* next entry */ struct route_cond *next; /* next entry */
@ -263,7 +256,6 @@ extern struct route_ruleset *ruleset_first;
extern struct route_ruleset *ruleset_main; extern struct route_ruleset *ruleset_main;
extern struct route_action action_external; extern struct route_action action_external;
extern struct route_action action_internal; extern struct route_action action_internal;
extern struct route_action action_h323;
extern struct route_action action_chan; extern struct route_action action_chan;
extern struct route_action action_vbox; extern struct route_action action_vbox;
extern struct route_action action_partyline; extern struct route_action action_partyline;

View File

@ -3,7 +3,7 @@ define and change dsp conference ids
make asterisk call implementation make asterisk call implementation
new interface.conf new interface.conf (add remove ports by admin)
reduce mixer reduce mixer
@ -20,10 +20,9 @@ trace with layers and filters
- application process (action) - application process (action)
- bchannel control (tones, dsp, filter, activation/deactivation) - bchannel control (tones, dsp, filter, activation/deactivation)
sip raus, h323 raus
avoid disconnect-collision (release if disconnect from both sides) avoid disconnect-collision (release if disconnect from both sides)
display message during nothing/play

84
tones.c
View File

@ -276,6 +276,7 @@ int open_tone(char *file, int *codec, signed long *length, signed long *left)
/* /*
* read from tone, check size * read from tone, check size
* the len must be the number of samples, NOT for the bytes to read!! * the len must be the number of samples, NOT for the bytes to read!!
* the data returned is law-code
*/ */
int read_tone(int fh, void *buffer, int codec, int len, signed long size, signed long *left, int speed) int read_tone(int fh, void *buffer, int codec, int len, signed long size, signed long *left, int speed)
{ {
@ -319,15 +320,29 @@ int read_tone(int fh, void *buffer, int codec, int len, signed long size, signed
break; break;
case CODEC_MONO: case CODEC_MONO:
l = read(fh, buffer, len<<1); /* as is */ signed short buffer16[len], *buf16 = buffer16;
if (l>0) signed long sample;
l = l>>1; int i = 0;
l = read(fh, buf16, len<<1);
if (l>0)
{
l = l>>1;
while(i < l)
{
sample = *buf16++;
if (sample < -32767)
sample = -32767;
if (sample > 32767)
sample = 32767;
*buffer++ = audio_s16_to_law[sample & 0xffff];
i++;
}
}
break; break;
case CODEC_STEREO: case CODEC_STEREO:
{ {
signed short buffer32[len<<1], *buf32 = buffer32; signed short buffer32[len<<1], *buf32 = buffer32;
signed short *buf16 = (signed short *)buffer;
signed long sample; signed long sample;
int i = 0; int i = 0;
l = read(fh, buf32, len<<2); l = read(fh, buf32, len<<2);
@ -341,7 +356,7 @@ int read_tone(int fh, void *buffer, int codec, int len, signed long size, signed
sample = -32767; sample = -32767;
if (sample > 32767) if (sample > 32767)
sample = 32767; sample = 32767;
*buf16++ = sample; *buffer++ = audio_s16_to_law[sample & 0xffff];
i++; i++;
} }
} }
@ -351,14 +366,13 @@ int read_tone(int fh, void *buffer, int codec, int len, signed long size, signed
case CODEC_8BIT: case CODEC_8BIT:
{ {
unsigned char buffer8[len], *buf8 = buffer8; unsigned char buffer8[len], *buf8 = buffer8;
signed short *buf16 = (signed short *)buffer;
int i = 0; int i = 0;
l = read(fh, buf8, len); l = read(fh, buf8, len);
if (l>0) if (l>0)
{ {
while(i < l) while(i < l)
{ {
*buf16++ = (((*buf8++) << 8) - 0x8000) & 0xffff; *buffer++ = audio_s16_to_law[(((*buf8++)<<8)-0x8000) & 0xffff];
i++; i++;
} }
} }
@ -366,7 +380,7 @@ int read_tone(int fh, void *buffer, int codec, int len, signed long size, signed
break; break;
default: default:
PERROR("codec %d is not specified or supported, exitting...\n", codec); PERROR("codec %d is not supported, exitting...\n", codec);
exit(-1); exit(-1);
} }
@ -420,7 +434,7 @@ int fetch_tones(void)
char filename[256], name[256]; char filename[256], name[256];
int fh; int fh;
int tone_codec; int tone_codec;
signed long tone_size, tone_left, real_size; signed long tone_size, tone_left;
unsigned long memory = 0; unsigned long memory = 0;
int samples = 0; int samples = 0;
@ -515,32 +529,8 @@ int fetch_tones(void)
continue; continue;
} }
/* real size */
switch(tone_codec)
{
case CODEC_LAW:
real_size = tone_size;
break;
case CODEC_MONO:
real_size = tone_size << 1;
break;
case CODEC_STEREO:
real_size = tone_size << 1;
break;
case CODEC_8BIT:
real_size = tone_size << 1;
break;
default:
PERROR("codec %d is not specified or supported, exitting...\n", tone_codec);
exit(-1);
}
/* allocate tone */ /* allocate tone */
*tonesettone_nextpointer = (struct tonesettone *)calloc(1, sizeof(struct tonesettone)+real_size); *tonesettone_nextpointer = (struct tonesettone *)calloc(1, sizeof(struct tonesettone)+tone_size);
if (*toneset_nextpointer == NULL) if (*toneset_nextpointer == NULL)
{ {
PERROR("No memory for tone set: '%s'\n",p); PERROR("No memory for tone set: '%s'\n",p);
@ -550,8 +540,8 @@ int fetch_tones(void)
} }
memuse++; memuse++;
//printf("tone:%s, %ld bytes\n", name, tone_size); //printf("tone:%s, %ld bytes\n", name, tone_size);
memset(*tonesettone_nextpointer, 0 , sizeof(struct tonesettone)+real_size); memset(*tonesettone_nextpointer, 0 , sizeof(struct tonesettone)+tone_size);
memory += sizeof(struct tonesettone)+real_size; memory += sizeof(struct tonesettone)+tone_size;
samples ++; samples ++;
/* load tone */ /* load tone */
@ -629,7 +619,7 @@ void *open_tone_fetched(char *dir, char *file, int *codec, signed long *length,
* read from fetched tone, check size * read from fetched tone, check size
* the len must be the number of samples, NOT for the bytes to read!! * the len must be the number of samples, NOT for the bytes to read!!
*/ */
int read_tone_fetched(void **fetched, void *buffer, int codec, int len, signed long size, signed long *left, int speed) int read_tone_fetched(void **fetched, void *buffer, int len, signed long size, signed long *left, int speed)
{ {
int l; int l;
//printf("left=%ld\n",*left); //printf("left=%ld\n",*left);
@ -643,24 +633,10 @@ int read_tone_fetched(void **fetched, void *buffer, int codec, int len, signed l
if (*left < len) if (*left < len)
len = *left; len = *left;
switch(codec)
{
case CODEC_LAW:
memcpy(buffer, *fetched, len);
*((char **)fetched) += len;
l = len;
break;
case CODEC_MONO: memcpy(buffer, *fetched, len);
memcpy(buffer, *fetched, len<<1); *((char **)fetched) += len;
*((char **)fetched) += len<<1; l = len;
l = len;
break;
default:
PERROR("codec %d is not specified or supported, exitting...\n", codec);
exit(-1);
}
if (l>0 && left) if (l>0 && left)
*left -= l; *left -= l;

View File

@ -62,9 +62,13 @@ int VBoxPort::handler(void)
{ {
struct message *message; struct message *message;
unsigned long tosend; unsigned long tosend;
signed short buffer[128<<1]; signed short buffer[128];
time_t currenttime; time_t currenttime;
class Endpoint *epoint; class Endpoint *epoint;
int ret;
if ((ret = Port::handler()))
return(ret);
if (p_vbox_record_start && p_vbox_record_limit) if (p_vbox_record_start && p_vbox_record_limit)
{ {
@ -98,7 +102,7 @@ int VBoxPort::handler(void)
/* wait for more */ /* wait for more */
if (tosend < 32) if (tosend < 32)
return(0); return(Port::handler());
/* too many samples, so we just process 128 bytes until the next call of handler() */ /* too many samples, so we just process 128 bytes until the next call of handler() */
if (tosend > 128) if (tosend > 128)
@ -113,23 +117,7 @@ int VBoxPort::handler(void)
/* if announcement is currently played, send audio data */ /* if announcement is currently played, send audio data */
if (p_vbox_announce_fh >=0) if (p_vbox_announce_fh >=0)
{ {
/* read from announcement file */ tosend = read_tone(p_vbox_announce_fh, buffer, p_vbox_announce_codec, tosend, p_vbox_announce_size, &p_vbox_announce_left, 1);
switch(p_vbox_announce_codec)
{
case CODEC_LAW:
tosend = read_tone(p_vbox_announce_fh, buffer, p_vbox_announce_codec, tosend, p_vbox_announce_size, &p_vbox_announce_left, 1);
break;
case CODEC_MONO:
case CODEC_STEREO:
case CODEC_8BIT:
tosend = read_tone(p_vbox_announce_fh, buffer, p_vbox_announce_codec, tosend, p_vbox_announce_size, &p_vbox_announce_left, 1);
break;
default:
PERROR("correct codec not given.\n");
exit(-1);
}
if (tosend <= 0) if (tosend <= 0)
{ {
/* end of file */ /* end of file */
@ -175,34 +163,12 @@ int VBoxPort::handler(void)
} }
} else } else
{ {
switch(p_vbox_announce_codec) message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DATA);
{ message->param.data.port_type = p_type;
case CODEC_LAW: message->param.data.port_id = p_serial;
message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DATA); message->param.data.len = tosend;
message->param.data.compressed = 1; memcpy(message->param.data.data, buffer, tosend);
message->param.data.port_type = p_type; message_put(message);
message->param.data.port_id = p_serial;
message->param.data.len = tosend;
memcpy(message->param.data.data, buffer, tosend);
message_put(message);
break;
case CODEC_MONO:
case CODEC_STEREO:
case CODEC_8BIT:
message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DATA);
message->param.data.compressed = 0;
message->param.data.port_type = p_type;
message->param.data.port_id = p_serial;
message->param.data.len = tosend<<1;
memcpy(message->param.data.data, buffer, tosend<<1);
message_put(message);
break;
default:
PERROR("correct announce_codec not given.\n");
exit(-1);
}
} }
} }
@ -221,6 +187,9 @@ int VBoxPort::message_epoint(unsigned long epoint_id, int message_id, union para
char filename[256], *c; char filename[256], *c;
class EndpointAppPBX *eapp; class EndpointAppPBX *eapp;
if (Port::message_epoint(epoint_id, message_id, param))
return(1);
epoint = find_epoint_id(epoint_id); epoint = find_epoint_id(epoint_id);
if (!epoint) if (!epoint)
{ {
@ -228,9 +197,6 @@ int VBoxPort::message_epoint(unsigned long epoint_id, int message_id, union para
return(0); return(0);
} }
if (Port::message_epoint(epoint_id, message_id, param))
return(1);
switch(message_id) switch(message_id)
{ {
case MESSAGE_DISCONNECT: /* call has been disconnected */ case MESSAGE_DISCONNECT: /* call has been disconnected */