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
# 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_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
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
MISDNUSER_INCLUDE = -I../mISDNuser/include
@ -46,28 +39,10 @@ GENRC = ./genrc
GENEXT = ./genextension
CFLAGS = -Wall -g -DINSTALL_DATA=\"$(INSTALL_DATA)\"
CFLAGS += $(LINUX_INCLUDE) $(MISDNUSER_INCLUDE)
ifdef WITH-PBX
CFLAGS += -DPBX
endif
ifdef WITH-CRYPTO
CFLAGS += -DCRYPTO
endif
CFLAGS_OPAL = $(CFLAGS)
CFLAGS_H323 = $(CFLAGS)
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
LIBDIR += -L/usr/local/ssl/lib
CFLAGS += -I/usr/local/ssl/include
@ -92,7 +67,7 @@ all: $(PBXADMIN) $(PBX) $(GEN) $(GENW) $(GENRC) $(GENEXT)
@exit
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
$(CC) -c $(CFLAGS) message.c -o message.o
@ -103,9 +78,6 @@ options.o: options.c *.h Makefile
interface.o: interface.c *.h Makefile
$(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
$(CC) -c $(CFLAGS) extension.c -o extension.o
@ -184,18 +156,6 @@ tones.o: tones.c *.h Makefile
crypt.o: crypt.cpp *.h Makefile
$(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
$(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 \
# -o $(WIZZARD)
$(PBX): $(H323) $(OPAL) \
main.o \
$(PBX): main.o \
options.o \
interface.o \
h323conf.o \
extension.o \
cause.o \
alawulaw.o \
@ -237,11 +195,10 @@ $(PBX): $(H323) $(OPAL) \
callpbx.o \
callchan.o \
admin_server.o
$(LD) $(LIBDIR) $(H323) $(OPAL) \
$(LD) $(LIBDIR) \
main.o \
options.o \
interface.o \
h323conf.o \
extension.o \
cause.o \
alawulaw.o \
@ -318,9 +275,6 @@ install:
echo "NOTE: numbering_int.conf is obsolete, please use routing." ; fi
@if test -a $(INSTALL_DATA)/numbering_ext.conf ; then \
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 \
echo "NOTE: directory.list already exists, not changed." ; else \
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 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)
{
@ -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)
{
struct port_list *portlist = ea_endpoint->ep_portlist;
@ -1412,9 +986,6 @@ void EndpointAppPBX::_action_redial_reply(int in)
if (!strncmp(last, "intern:", 7))
SPRINT(message->param.notifyinfo.display, "(%d) %s int", e_select+1, last+7);
else
if (!strncmp(last, "h323:", 5))
SPRINT(message->param.notifyinfo.display, "(%d) %s h323", e_select+1, last+5);
else
if (!strncmp(last, "chan:", 4))
SPRINT(message->param.notifyinfo.display, "(%d) %s chan", e_select+1, last+5);
else
@ -2629,13 +2200,6 @@ void EndpointAppPBX::process_dialing(void)
e_action = &action_internal;
goto process_action;
}
/* check for h323 call */
if (!strncmp(e_dialinginfo.number, "h323:", 5))
{
e_extdialing = e_dialinginfo.number+5;
e_action = &action_h323;
goto process_action;
}
/* check for chan call */
if (!strncmp(e_dialinginfo.number, "chan:", 5))
{
@ -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);
switch(e_dialinginfo.itype)
{
case INFO_ITYPE_H323:
SPRINT(dialingtext, "h323:%s", e_dialinginfo.number);
break;
case INFO_ITYPE_CHAN:
SPRINT(dialingtext, "chan:%s", e_dialinginfo.number);
break;

View File

@ -236,9 +236,6 @@ int admin_route(struct admin_queue **responsep)
case ACTION_EXTERNAL:
apppbx->e_action = &action_external;
break;
case ACTION_H323:
apppbx->e_action = &action_h323;
break;
case ACTION_CHAN:
apppbx->e_action = &action_chan;
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)
*/
void EndpointAppPBX::release(int release, int calllocation, int callcause, int portlocation, int portcause)
@ -1138,91 +1226,6 @@ void EndpointAppPBX::out_setup(void)
}
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 */
default:
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;
char buffer[256];
struct interface *interface;
char extension[32];
char extension1[32];
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));
e_dtmf = param->setup.dtmf;
/* check where the call is from */
/* screen by interface */
if (e_callerinfo.interface[0])
{
interface = interface_first;
while(interface)
{
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;
}
/* screen incoming caller id */
screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present);
}
colp, outclip, outcolp
/* process extension */
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 */
SCPY(e_callerinfo.id, e_callerinfo.intern);
SCPY(e_callerinfo.intern, e_callerinfo.id);
SCPY(e_terminal, e_callerinfo.intern);
SCPY(e_terminal_interface, e_callerinfo.interface);
} 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",
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.present==INFO_PRESENT_RESTRICTED)?" anonymous":"",
(e_redirinfo.id[0])?"redirected='":"",
@ -2204,6 +2126,13 @@ void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type,
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 */
if (e_ext.name[0])
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;
}
}
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);
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);
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 */
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));
message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
}
/* use internal caller id */
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);
message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
}
/* 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);
/* 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));
/* use conp, if enabld */
if (!e_ext.centrex)
message->param.connectinfo.name[0] = '\0';
/* send connect */
message_put(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_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 */
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
);
}
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)
{
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_dialed[0] = '\0';
c_todial[0] = '\0';
c_mixer = 0;
c_pid = getpid();
c_updatebridge = 0;
c_partyline = 0;
/* initialize a relation only to the calling interface */
@ -298,23 +299,26 @@ CallPBX::~CallPBX()
}
/* mixer sets the mixer of hisax bchannels
* the mixer() will set the mixer for the hisax ports which is done
* at kernel space.
/* bridge sets the audio flow of all bchannels assiociated to 'this' call
* also it changes and notifies active/hold/conference states
*/
void CallPBX::mixer(void)
void CallPBX::bridge(void)
{
struct call_relation *relation;
struct message *message;
int numconnect, relations;
int numconnect = 0, relations = 0;
class Endpoint *epoint;
struct port_list *portlist;
class Port *port;
int nodata = 1;
int allmISDN = 0; // relations that are no mISDN
relation = c_relation;
while(relation)
{
/* count all relations */
relations++;
/* check for relation's objects */
epoint = find_epoint_id(relation->epoint_id);
if (!epoint)
{
@ -325,7 +329,7 @@ void CallPBX::mixer(void)
portlist = epoint->ep_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
relation->channel_state = CHANNEL_STATE_HOLD;
relation = relation->next;
@ -342,38 +346,44 @@ void CallPBX::mixer(void)
port = find_port_id(portlist->port_id);
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;
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)
{
PDEBUG((DEBUG_CALL|DEBUG_PORT), "ignoring relation ep%d because it is not mISDN.\n", epoint->ep_serial);
if (nodata)
PDEBUG((DEBUG_CALL|DEBUG_PORT), "ignoring relation ep%d because it's port is not mISDN.\n", epoint->ep_serial);
if (allmISDN)
{
PDEBUG((DEBUG_CALL|DEBUG_PORT), "not all endpoints are mISDN.\n");
nodata = 0;
allmISDN = 0;
}
relation = relation->next;
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
&& 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->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);
message_put(message);
} 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);
message_put(message);
}
relation = relation->next;
}
/* we notify all relations about rxdata. */
relation = c_relation;
while(relation)
{
/*
* request data from endpoint/port if:
* - two relations
* - any without mISDN
* in this case we bridge
*/
message = message_create(c_serial, relation->epoint_id, CALL_TO_EPOINT, MESSAGE_mISDNSIGNAL);
message->param.mISDNsignal.message = mISDNSIGNAL_NODATA;
message->param.mISDNsignal.nodata = nodata;
PDEBUG(DEBUG_CALL, "call %d sets alldata on port %s to %d\n", c_serial, port->p_name, nodata);
message->param.mISDNsignal.message = mISDNSIGNAL_CALLDATA;
message->param.mISDNsignal.calldata = (relnum==2 && !allmISDN);
PDEBUG(DEBUG_CALL, "call %d sets 'calldata' on port %s to %d\n", c_serial, port->p_name, calldata);
message_put(message);
relation = relation->next;
}
/* count relations and states */
relation = c_relation;
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 */
/* two people just exchange their states */
if (relations==2 && !c_partyline)
{
relation = c_relation;
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);
} 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;
while(relation)
@ -444,52 +444,45 @@ void CallPBX::mixer(void)
}
}
/* send audio data to endpoints which do not come from an endpoint connected
* 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
/*
* bridging is only possible with two connected endpoints
*/
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 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 */
if (relation_from->channel_state != CHANNEL_STATE_CONNECT)
{
return;
}
/* loop all endpoints and skip the endpoint where the audio is from
* so we do not get a loop (echo)
*/
/* get destination relation */
relation_to = c_relation;
while(relation_to)
if (relation_to == relation_from)
{
/* skip source endpoint */
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);
/* oops, we are the first, so destination is: */
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;
}
/* remove from mixer */
/* remove from bridge */
if (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 */
@ -738,7 +731,7 @@ void CallPBX::message_epoint(unsigned long epoint_id, int message_type, union pa
if (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)
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)
{
relation->rx_state = new_state;
c_mixer = 1;
c_updatebridge = 1;
if (options.deb & DEBUG_CALL)
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 */
case MESSAGE_DATA:
/* now send audio data to all endpoints connected */
call_mixer(epoint_id, relation, param);
/* now send audio data to the other endpoint */
bridge_data(epoint_id, relation, param);
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->param.setup.partyline = c_partyline;
message_put(message);
c_mixer = 1; /* update mixer flag */
c_updatebridge = 1; /* update bridge flag */
}
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.location = LOCATION_PRIVATE_LOCAL;
message_put(message);
// c_mixer = 1; /* update mixer flag */
// c_updatebridge = 1; /* update bridge flag */
return;
}
}
@ -880,11 +873,11 @@ int CallPBX::handler(void)
// int i, j;
// char *p;
/* the mixer must be updated */
if (c_mixer)
/* the bridge must be updated */
if (c_updatebridge)
{
mixer();
c_mixer = 0;
bridge();
c_updatebridge = 0;
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
beim letzten den collected cause senden
mixer kann ruhig loslegen, das aber dokumentieren
mixer überdenken: wer sendet, welche töne verfügbar sind, u.s.w
bridge kann ruhig loslegen, das aber dokumentieren
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_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 */
int c_partyline; /* if set, call is conference room */
void mixer(void);
void call_mixer(unsigned long epoint_from, struct call_relation *relation_from, union parameter *param);
void bridge(void);
void bridge_data(unsigned long epoint_from, struct call_relation *relation_from, union parameter *param);
void remove_relation(struct call_relation *relation);
struct call_relation *add_relation(void);
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;
}
p_callerinfo.isdn_port = p_m_portnum;
SCPY(p_callerinfo.interface, p_m_mISDNport->ifport->interface->name);
/* 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_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->param.setup.isdn_port = p_m_portnum;
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.callerinfo, &p_callerinfo, sizeof(struct caller_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;
}
p_connectinfo.isdn_port = p_m_portnum;
SCPY(p_connectingo.interface, p_m_mISDNport->ifport->interface->name);
#ifdef CENTREX
/* te-mode: CONP (connected name identification presentation) */
if (!p_m_d_ntmode)
@ -2100,6 +2100,11 @@ void Pdss1::new_state(int state)
*/
int Pdss1::handler(void)
{
int ret;
if ((ret = Port::handler()))
return(ret);
/* handle destruction */
if (p_m_delete && p_m_d_l3id==0)
{
@ -2108,7 +2113,7 @@ int Pdss1::handler(void)
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);
}
} 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"))
{
i=0;
@ -1293,10 +1275,6 @@ int write_extension(struct extension *ext, char *number)
fprintf(fp,"# example: \"200 (int)\"\n");
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,"# This makes only sense if the anon-ignore feature is enabled.\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++;
memset(ifscreen, 0, sizeof(struct interface_screen));
#warning handle unchanged as unchanged!!
ifscreen->match_type = -1; /* unchecked */
ifscreen->match_present = -1; /* unchecked */
ifscreen->result_type = -1; /* unchanged */
ifscreen->result_present = -1; /* unchanged */
/* tail port */
@ -554,7 +556,7 @@ static int inter_screen(struct interface_screen **ifscreenp, struct interface *i
if (ifscreen->match_present != -1)
{
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);
}
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;
} else {
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;
}
}
@ -616,6 +627,15 @@ static int inter_screen(struct interface_screen **ifscreenp, struct interface *i
ifscreen->result_present = INFO_PRESENT_RESTRICTED;
} else {
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;
}
}
@ -716,10 +736,13 @@ struct interface_param interface_param[] = {
"Adds an entry for outgoing calls to the caller ID screen list.\n"
"See 'screen-in' for help."},
#if 0
#warning todo: filter, also in the PmISDN object
{"filter", &inter_filter, "<filter> [parameters]",
"Adds/appends a filter. Filters are ordered in transmit direction.\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."},
#endif
{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_txvol = p_m_rxvol = 0;
p_m_conf = 0;
p_m_txdata = 0;
#warning set delay by routing parameter or interface config
p_m_delay = 0;
p_m_echo = 0;
p_m_tone = 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_dtmf = !options.nodtmf;
sollen wir daraus eine interface-option machen?:
p_m_timeout = 0;
p_m_timer = 0;
#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 */
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)
{
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);
ph_control(mISDNport->b_addr[i], CMX_RECEIVE_OFF, 0);
}
#if 0
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);
ph_control(mISDNport->b_addr[i], CMX_MIX_ON, 0);
}
#endif
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);
@ -285,6 +292,11 @@ static void bchannel_deactivate(struct mISDNport *mISDNport, int i)
/* reset dsp features */
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)
{
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);
ph_control(mISDNport->b_addr[i], CMX_RECEIVE_ON, 0);
}
#if 0
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);
ph_control(mISDNport->b_addr[i], CMX_MIX_OFF, 0);
}
#endif
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);
@ -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))
{
//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)
{
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);
}
}
#endif
if (p_m_crypt_msg_loops)
{
/* send pending message */
@ -667,11 +683,13 @@ void PmISDN::bchannel_receive(iframe_t *frm)
{
p_m_crypt_msg_current = 0;
p_m_crypt_msg_loops--;
#if 0
// we need to disable rxmix some time after sending the loops...
if (!p_m_crypt_msg_loops && p_m_txmix)
{
p_m_txmix_on = 8000; /* one sec */
}
#endif
}
}
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);
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:
p_m_nodata = param->mISDNsignal.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);
}
break;
#endif
#if 0
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_loops = 3; /* enable */
#if 0
/* disable txmix, or we get corrupt data due to audio process */
if (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);
}
#endif
break;
default:
@ -1017,6 +1048,9 @@ int mISDN_handler(void)
mISDNuser_head_t *hh;
int i;
if ((ret = Port::handler()))
return(ret);
/* the que avoids loopbacks when replying to stack after receiving
* from stack. */
mISDNport = mISDNport_first;

View File

@ -101,8 +101,8 @@ class PmISDN : public Port
int p_m_tone; /* current kernel space tone */
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_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; /* 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_dtmf; /* dtmf decoding 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 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 mmemuse = 0;
int cmemuse = 0;
@ -277,15 +244,7 @@ int main(int argc, char *argv[])
GET_NOW();
/* 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);
#endif
#endif
/* show options */
if (ARGC <= 1)
@ -485,39 +444,6 @@ int main(int argc, char *argv[])
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 */
if (!read_interfaces())
{
@ -591,10 +517,6 @@ int main(int argc, char *argv[])
while(!quit)
{
/* 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;
/* handle mISDN messages from kernel */
@ -801,12 +723,6 @@ BUDETECT
GET_NOW();
#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 */
if (all_idle)
{
@ -822,7 +738,6 @@ free:
/* set scheduler & priority
* we must remove realtimeshed, because h323 may lock during exit
*/
if (options.schedule > 1)
{
@ -840,9 +755,6 @@ free:
}
/* destroy objects */
#ifdef H323
mutex_h323.Wait();
#endif
debug_prefix = "free";
while(port_first)
@ -880,37 +792,6 @@ free:
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 */
if (toneset_first)
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_PORT 0x0100
#define DEBUG_ISDN 0x0110
#define DEBUG_OPAL 0x0120
#define DEBUG_H323 0x0130
//#define DEBUG_KNOCK 0x0140
#define DEBUG_VBOX 0x0180
#define DEBUG_EPOINT 0x0200
@ -60,31 +58,18 @@ void _printerror(const char *function, int line, const char *fmt, ...);
*/
#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
* 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.
/*
* transmit interval for tones and announcements (or samples of all kind)
*
*/
#ifdef VOIP
#warning to be removed soon
#endif
#define PORT_BUFFER 768
#define ISDN_TRANSMIT 128
/* keep this 0 for minimum delay */
#ifdef VOIP
#warning to be removed soon
#endif
/*
* preload transmit buffer to avoid gaps at the beginning due to jitter
* keep this 0 for minimum delay
*/
#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")
*/
#define SENDMAIL "sendmail"
@ -118,28 +103,6 @@ void _printerror(const char *function, int line, const char *fmt, ...);
#define BUDETECT ;
#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 <stdlib.h>
#include <unistd.h>
@ -158,7 +121,6 @@ extern "C" {
#include "save.h"
#include "options.h"
#include "interface.h"
#include "h323conf.h"
#include "extension.h"
#include "message.h"
#include "endpoint.h"
@ -168,12 +130,6 @@ extern "C" {
#include "port.h"
#include "mISDN.h"
#include "dss1.h"
#ifdef H323
#include "h323.h"
#endif
#ifdef OPAL
#include "opal.h"
#endif
#include "vbox.h"
#include "call.h"
#include "callpbx.h"
@ -191,12 +147,4 @@ extern struct timeval now_tv;
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 **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 */
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 */
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)
{
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->next);
//#ifdef H323
// mutex_message.Signal();
//#endif
}
@ -89,16 +76,8 @@ struct message *message_get(void)
{
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)
{
//#ifdef H323
// mutex_message.Signal();
//#endif
return(0);
}
@ -107,10 +86,6 @@ struct message *message_get(void)
if (!message_first)
messagepointer_end = &message_first;
//#ifdef H323
// mutex_message.Signal();
//#endif
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);

View File

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

171
options.c
View File

@ -31,12 +31,6 @@ struct options options = {
"tones_american", /* directory of tones */
"", /* directories of tones to fetch */
"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 */
"", /* dummy caller id */
0, /* use tones by dsp.o */
@ -57,9 +51,6 @@ int read_options(void)
char param[256];
unsigned int line,i;
char buffer[256];
#ifdef H323
int codecpri = 0;
#endif
SPRINT(filename, "%s/options.conf", INSTALL_DATA);
@ -189,168 +180,6 @@ int read_options(void)
PDEBUG(DEBUG_CONFIG, "isdn audio type: ulaw\n");
} 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 (param[0]==0)

View File

@ -22,28 +22,6 @@ struct options {
char tones_dir[64]; /* directory of all tones/patterns */
char fetch_tones[256]; /* directories of tones to fetch */
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 */
char dummyid[32]; /* caller id for external calls if not available */
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 */
#define PORT_TYPE_DSS1_TE_IN 0x0113
#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 */
#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_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 */
unsigned long p_serial; /* serial unique id of port */
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 cond_defs cond_defs[] = {
#ifdef PBX
{ "extern", MATCH_EXTERN, COND_TYPE_NULL,
"extern", "Matches if call is from external port."},
{ "intern", MATCH_INTERN, COND_TYPE_NULL,
"intern", "Matches if call is from internal port."},
#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)."},
"extern", "Matches if call is from external port (no extension)."},
{ "intern", MATCH_INTERN,COND_TYPE_NULL,
"intern", "Matches if call is from an extension."},
{ "port", MATCH_PORT, COND_TYPE_INTEGER,
"port=<number>[-<number>][,...]", "Matches if call is received from given port(s). NOT INTERFACE!"},
{ "interface", MATCH_INTERFACE,COND_TYPE_STRING,
@ -111,14 +105,12 @@ struct param_defs param_defs[] = {
{ PARAM_CONNECT,
"connect", PARAM_TYPE_NULL,
"connect", "Will complete the call before processing the action. Audio path for external calls will be established."},
#ifdef PBX
{ PARAM_EXTENSION,
"extension", PARAM_TYPE_STRING,
"extension=<digits>", "Give extension name (digits) to relate this action to."},
{ PARAM_EXTENSIONS,
"extensions", PARAM_TYPE_STRING,
"extensions=<extension>[,<extension>[,...]]", "One or more extensions may be given."},
#endif
{ PARAM_PREFIX,
"prefix", PARAM_TYPE_STRING,
"prefix=<digits>", "Add prefix in front of the dialed number."},
@ -170,11 +162,9 @@ struct param_defs param_defs[] = {
{ PARAM_SAMPLE,
"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."},
#ifdef PBX
{ PARAM_ANNOUNCEMENT,
"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."},
#endif
{ PARAM_RULESET,
"ruleset", PARAM_TYPE_STRING,
"ruleset=<name>", "Ruleset to go to."},
@ -229,11 +219,9 @@ struct param_defs param_defs[] = {
{ PARAM_TIMEOUT,
"timeout", PARAM_TYPE_INTEGER,
"timeout=<seconds>", "Timeout before continue with next action."},
#ifdef PBX
{ PARAM_NOPASSWORD,
"nopassword", PARAM_TYPE_NULL,
"nopassword", "Don't ask for password. Be sure to authenticate right via real caller ID."},
#endif
{ 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,
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'"},
{ 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,
"asterisk", &EndpointAppPBX::action_init_chan, &EndpointAppPBX::action_dialing_chan, &EndpointAppPBX::action_hangup_call,
PARAM_CONNECT | PARAM_TIMEOUT,
@ -2038,13 +2022,6 @@ struct route_action *EndpointAppPBX::route(struct route_ruleset *ruleset)
istrue = 1;
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:
if (ea_endpoint->ep_portlist)
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,
};
struct route_action action_h323 = {
NULL,
NULL,
ACTION_H323,
0,
0,
};
struct route_action action_chan = {
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 */
#ifdef PBX
MATCH_EXTERN,
MATCH_INTERN,
#endif
MATCH_H323,
// MATCH_IP,
MATCH_PORT,
MATCH_INTERFACE,
MATCH_CALLERID,
@ -96,10 +92,8 @@ enum { /* how to parse text file during startup */
#define PARAM_PROCEEDING 1LL
#define PARAM_ALERTING (1LL<<1)
#define PARAM_CONNECT (1LL<<2)
#ifdef PBX
#define PARAM_EXTENSION (1LL<<3)
#define PARAM_EXTENSIONS (1LL<<4)
#endif
#define PARAM_PREFIX (1LL<<5)
#define PARAM_CAPA (1LL<<6)
#define PARAM_BMODE (1LL<<7)
@ -149,37 +143,36 @@ enum { /* how to parse text file during startup */
#define ACTION_EXTERNAL 0
#define ACTION_INTERNAL 1
#define ACTION_OUTDIAL 2
#define ACTION_H323 3
#define ACTION_CHAN 4
#define ACTION_VBOX_RECORD 5
#define ACTION_PARTYLINE 6
#define ACTION_LOGIN 7
#define ACTION_CALLERID 8
#define ACTION_CALLERIDNEXT 9
#define ACTION_FORWARD 10
#define ACTION_REDIAL 11
#define ACTION_REPLY 12
#define ACTION_POWERDIAL 13
#define ACTION_CALLBACK 14
#define ACTION_ABBREV 15
#define ACTION_TEST 16
#define ACTION_PLAY 17
#define ACTION_VBOX_PLAY 18
#define ACTION_CALCULATOR 19
#define ACTION_TIMER 20
#define ACTION_GOTO 21
#define ACTION_MENU 22
#define ACTION_DISCONNECT 23
#define ACTION_HELP 24
#define ACTION_DEFLECT 25
#define ACTION_SETFORWARD 26
#define ACTION_EXECUTE 27
#define ACTION_FILE 28
#define ACTION_PICK 29
#define ACTION_PASSWORD 30
#define ACTION_PASSWORD_WRITE 31
#define ACTION_NOTHING 32
#define ACTION_EFI 33
#define ACTION_CHAN 3
#define ACTION_VBOX_RECORD 4
#define ACTION_PARTYLINE 5
#define ACTION_LOGIN 6
#define ACTION_CALLERID 7
#define ACTION_CALLERIDNEXT 8
#define ACTION_FORWARD 9
#define ACTION_REDIAL 10
#define ACTION_REPLY 11
#define ACTION_POWERDIAL 12
#define ACTION_CALLBACK 13
#define ACTION_ABBREV 14
#define ACTION_TEST 15
#define ACTION_PLAY 16
#define ACTION_VBOX_PLAY 17
#define ACTION_CALCULATOR 18
#define ACTION_TIMER 19
#define ACTION_GOTO 20
#define ACTION_MENU 21
#define ACTION_DISCONNECT 22
#define ACTION_HELP 23
#define ACTION_DEFLECT 24
#define ACTION_SETFORWARD 25
#define ACTION_EXECUTE 26
#define ACTION_FILE 27
#define ACTION_PICK 28
#define ACTION_PASSWORD 29
#define ACTION_PASSWORD_WRITE 30
#define ACTION_NOTHING 31
#define ACTION_EFI 32
struct route_cond { /* an item */
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_action action_external;
extern struct route_action action_internal;
extern struct route_action action_h323;
extern struct route_action action_chan;
extern struct route_action action_vbox;
extern struct route_action action_partyline;

View File

@ -3,7 +3,7 @@ define and change dsp conference ids
make asterisk call implementation
new interface.conf
new interface.conf (add remove ports by admin)
reduce mixer
@ -20,10 +20,9 @@ trace with layers and filters
- application process (action)
- bchannel control (tones, dsp, filter, activation/deactivation)
sip raus, h323 raus
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
* 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)
{
@ -319,15 +320,29 @@ int read_tone(int fh, void *buffer, int codec, int len, signed long size, signed
break;
case CODEC_MONO:
l = read(fh, buffer, len<<1); /* as is */
if (l>0)
l = l>>1;
signed short buffer16[len], *buf16 = buffer16;
signed long sample;
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;
case CODEC_STEREO:
{
signed short buffer32[len<<1], *buf32 = buffer32;
signed short *buf16 = (signed short *)buffer;
signed long sample;
int i = 0;
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;
if (sample > 32767)
sample = 32767;
*buf16++ = sample;
*buffer++ = audio_s16_to_law[sample & 0xffff];
i++;
}
}
@ -351,14 +366,13 @@ int read_tone(int fh, void *buffer, int codec, int len, signed long size, signed
case CODEC_8BIT:
{
unsigned char buffer8[len], *buf8 = buffer8;
signed short *buf16 = (signed short *)buffer;
int i = 0;
l = read(fh, buf8, len);
if (l>0)
{
while(i < l)
{
*buf16++ = (((*buf8++) << 8) - 0x8000) & 0xffff;
*buffer++ = audio_s16_to_law[(((*buf8++)<<8)-0x8000) & 0xffff];
i++;
}
}
@ -366,7 +380,7 @@ int read_tone(int fh, void *buffer, int codec, int len, signed long size, signed
break;
default:
PERROR("codec %d is not specified or supported, exitting...\n", codec);
PERROR("codec %d is not supported, exitting...\n", codec);
exit(-1);
}
@ -420,7 +434,7 @@ int fetch_tones(void)
char filename[256], name[256];
int fh;
int tone_codec;
signed long tone_size, tone_left, real_size;
signed long tone_size, tone_left;
unsigned long memory = 0;
int samples = 0;
@ -515,32 +529,8 @@ int fetch_tones(void)
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 */
*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)
{
PERROR("No memory for tone set: '%s'\n",p);
@ -550,8 +540,8 @@ int fetch_tones(void)
}
memuse++;
//printf("tone:%s, %ld bytes\n", name, tone_size);
memset(*tonesettone_nextpointer, 0 , sizeof(struct tonesettone)+real_size);
memory += sizeof(struct tonesettone)+real_size;
memset(*tonesettone_nextpointer, 0 , sizeof(struct tonesettone)+tone_size);
memory += sizeof(struct tonesettone)+tone_size;
samples ++;
/* 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
* 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;
//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)
len = *left;
switch(codec)
{
case CODEC_LAW:
memcpy(buffer, *fetched, len);
*((char **)fetched) += len;
l = len;
break;
case CODEC_MONO:
memcpy(buffer, *fetched, len<<1);
*((char **)fetched) += len<<1;
l = len;
break;
default:
PERROR("codec %d is not specified or supported, exitting...\n", codec);
exit(-1);
}
memcpy(buffer, *fetched, len);
*((char **)fetched) += len;
l = len;
if (l>0 && left)
*left -= l;

View File

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