Adding bridge between protocol handlers (ports)
This is required to bridge traffic beween non-mISDN handlers, such as GSM, SIP and voice box. Also it bridges traffic between mISDN handlers and non-mISDN handlers. It is the fundamental step to get rid of mISDN (loop interface) for non-mISDN handlers. This is required to bridge audio e.g. between SIP and GSM without using mISDN. There will be no limitations on 'b-channels' anymore. Still GSM and SIP requires mISDN, but this will be changed later. With that bridge I cleaned up some code and also removed the MESSAGE_DATA, which is not required anymore.
This commit is contained in:
parent
863bc64219
commit
877a2dfd52
15
Makefile.am
15
Makefile.am
|
@ -133,14 +133,13 @@ endif
|
|||
|
||||
INCLUDES = $(all_includes) $(GSM_INCLUDE) $(SS5_INCLUDE) $(SIP_INCLUDE) -Wall $(INSTALLATION_DEFINES)
|
||||
|
||||
lcr_SOURCES = $(GSM_SOURCE) $(SS5_SOURCE) $(SIP_SOURCE) select.c action.cpp mISDN.cpp \
|
||||
tones.c loop.c remote.cpp action_efi.cpp crypt.cpp mail.c trace.c \
|
||||
action_vbox.cpp dss1.cpp main.c \
|
||||
vbox.cpp alawulaw.c endpoint.cpp interface.c message.c \
|
||||
apppbx.cpp endpointapp.cpp join.cpp options.c \
|
||||
extension.c joinpbx.cpp port.cpp \
|
||||
callerid.c joinremote.cpp route.c \
|
||||
cause.c socket_server.c
|
||||
lcr_SOURCES = \
|
||||
main.c select.c trace.c \ options.c \ tones.c \ alawulaw.c \ cause.c \ interface.c \ message.c \ callerid.c \ socket_server.c \
|
||||
port.cpp \ vbox.cpp \ mISDN.cpp \ dss1.cpp \ loop.c remote.cpp \
|
||||
$(GSM_SOURCE) $(SS5_SOURCE) $(SIP_SOURCE) \
|
||||
endpoint.cpp \ endpointapp.cpp \
|
||||
apppbx.cpp \ route.c \ action.cpp action_efi.cpp \ action_vbox.cpp \ extension.c \ crypt.cpp \ mail.c \
|
||||
join.cpp \ joinpbx.cpp \ joinremote.cpp
|
||||
|
||||
lcr_LDADD = $(LIBCRYPTO) -lmisdn -lpthread $(GSM_LIB) $(SIP_LIB)
|
||||
|
||||
|
|
59
apppbx.cpp
59
apppbx.cpp
|
@ -2621,17 +2621,6 @@ void EndpointAppPBX::ea_message_port(unsigned int port_id, int message_type, uni
|
|||
|
||||
// PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
|
||||
switch(message_type) {
|
||||
case MESSAGE_DATA: /* data from port */
|
||||
/* check if there is a call */
|
||||
if (!ea_endpoint->ep_join_id)
|
||||
break;
|
||||
/* continue if only one portlist */
|
||||
if (ea_endpoint->ep_portlist->next != NULL)
|
||||
break;
|
||||
/* forward message */
|
||||
message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
|
||||
break;
|
||||
|
||||
case MESSAGE_TONE_EOF: /* tone is end of file */
|
||||
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
|
||||
if (e_action) {
|
||||
|
@ -3235,6 +3224,19 @@ void EndpointAppPBX::join_mISDNsignal(struct port_list *portlist, int message_ty
|
|||
}
|
||||
}
|
||||
|
||||
/* join MESSAGE_BRIDE */
|
||||
void EndpointAppPBX::join_bridge(struct port_list *portlist, int message_type, union parameter *param)
|
||||
{
|
||||
struct lcr_msg *message;
|
||||
|
||||
while(portlist) {
|
||||
message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_BRIDGE);
|
||||
memcpy(&message->param, param, sizeof(union parameter));
|
||||
message_put(message);
|
||||
portlist = portlist->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* join MESSAGE_NOTIFY */
|
||||
void EndpointAppPBX::join_notify(struct port_list *portlist, int message_type, union parameter *param)
|
||||
{
|
||||
|
@ -3316,21 +3318,6 @@ void EndpointAppPBX::ea_message_join(unsigned int join_id, int message_type, uni
|
|||
|
||||
portlist = ea_endpoint->ep_portlist;
|
||||
|
||||
/* send MESSAGE_DATA to port */
|
||||
if (message_type == MESSAGE_DATA) {
|
||||
if (join_id == ea_endpoint->ep_join_id) { // still linked with JOIN
|
||||
/* skip if no port relation */
|
||||
if (!portlist)
|
||||
return;
|
||||
/* skip if more than one port relation */
|
||||
if (portlist->next)
|
||||
return;
|
||||
/* forward audio data to port */
|
||||
message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// PDEBUG(DEBUG_EPOINT, "EPOINT(%d) received message %d for active JOIN (terminal %s, caller id %s state=%d)\n", ea_endpoint->ep_serial, message, e_ext.number, e_callerinfo.id, e_state);
|
||||
switch(message_type) {
|
||||
/* JOIN SENDS TONE message */
|
||||
|
@ -3420,23 +3407,11 @@ void EndpointAppPBX::ea_message_join(unsigned int join_id, int message_type, uni
|
|||
join_mISDNsignal(portlist, message_type, param);
|
||||
break;
|
||||
|
||||
#if 0
|
||||
kann nach dem test gelöscht werden, da eine direkte funktion im join und im mISDN zum austausch der message existiert
|
||||
/* JOIN requests bchannel */
|
||||
case MESSAGE_BCHANNEL: /* indicates the need of own bchannel access */
|
||||
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received bchannel assignment %d from join.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->bchannel.type);
|
||||
/* only one port is expected to be connected to bchannel */
|
||||
if (!portlist)
|
||||
break;
|
||||
if (portlist->next)
|
||||
break;
|
||||
e_join_pattern = 1;
|
||||
SCPY(e_tone, "");
|
||||
set_tone(portlist, NULL);
|
||||
message = message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
|
||||
logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
|
||||
/* JOIN sends bridge message */
|
||||
case MESSAGE_BRIDGE: /* bride message to port */
|
||||
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received bridge message.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
|
||||
join_bridge(portlist, message_type, param);
|
||||
break;
|
||||
#endif
|
||||
|
||||
/* JOIN has pattern available */
|
||||
case MESSAGE_PATTERN: /* indicating pattern available */
|
||||
|
|
1
apppbx.h
1
apppbx.h
|
@ -214,6 +214,7 @@ class EndpointAppPBX : public EndpointApp
|
|||
void ea_message_join(unsigned int join_id, int message, union parameter *param);
|
||||
void join_crypt(struct port_list *portlist, int message_type, union parameter *param);
|
||||
void join_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param);
|
||||
void join_bridge(struct port_list *portlist, int message_type, union parameter *param);
|
||||
void join_setup(struct port_list *portlist, int message_type, union parameter *param);
|
||||
void join_information(struct port_list *portlist, int message_type, union parameter *param);
|
||||
void join_overlap(struct port_list *portlist, int message_type, union parameter *param);
|
||||
|
|
4
genext.c
4
genext.c
|
@ -30,11 +30,11 @@ int fhuse = 0;
|
|||
struct isdn_cause isdn_cause[128];
|
||||
struct isdn_location isdn_location[16];
|
||||
|
||||
void _printdebug(const char *function, int line, unsigned int mask, const char *fmt, ...)
|
||||
void _printdebug(const char *file, const char *function, int line, unsigned int mask, const char *fmt, ...)
|
||||
{
|
||||
}
|
||||
|
||||
void _printerror(const char *function, int line, const char *fmt, ...)
|
||||
void _printerror(const char *file, const char *function, int line, const char *fmt, ...)
|
||||
{
|
||||
char buffer[4096];
|
||||
va_list args;
|
||||
|
|
58
joinpbx.cpp
58
joinpbx.cpp
|
@ -367,15 +367,12 @@ void JoinPBX::bridge(void)
|
|||
}
|
||||
|
||||
/*
|
||||
* request data from endpoint/port if:
|
||||
* - two relations
|
||||
* - any without mISDN
|
||||
* in this case we bridge
|
||||
* Bridge between port instances if:
|
||||
* - one or all are not mISDN
|
||||
*/
|
||||
message = message_create(j_serial, relation->epoint_id, JOIN_TO_EPOINT, MESSAGE_mISDNSIGNAL);
|
||||
message->param.mISDNsignal.message = mISDNSIGNAL_JOINDATA;
|
||||
message->param.mISDNsignal.joindata = (relations==2 && !allmISDN);
|
||||
PDEBUG(DEBUG_JOIN, "join%d EP%d set joindata=%d\n", j_serial, relation->epoint_id, message->param.mISDNsignal.joindata);
|
||||
message = message_create(j_serial, relation->epoint_id, JOIN_TO_EPOINT, MESSAGE_BRIDGE);
|
||||
message->param.bridge_id = j_serial;
|
||||
PDEBUG(DEBUG_JOIN, "join%u EP%u requests bridge=%u\n", j_serial, relation->epoint_id, message->param.bridge_id);
|
||||
message_put(message);
|
||||
|
||||
relation = relation->next;
|
||||
|
@ -413,43 +410,6 @@ void JoinPBX::bridge(void)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* bridging is only possible with two connected endpoints
|
||||
*/
|
||||
void JoinPBX::bridge_data(unsigned int epoint_from, struct join_relation *relation_from, union parameter *param)
|
||||
{
|
||||
struct join_relation *relation_to;
|
||||
|
||||
/* if we are alone */
|
||||
if (!j_relation->next)
|
||||
return;
|
||||
|
||||
/* if we are more than two */
|
||||
if (j_relation->next->next)
|
||||
return;
|
||||
|
||||
/* skip if source endpoint has NOT audio mode CONNECT */
|
||||
if (relation_from->channel_state != 1)
|
||||
return;
|
||||
|
||||
/* get destination relation */
|
||||
relation_to = j_relation;
|
||||
if (relation_to == relation_from) {
|
||||
/* oops, we are the first, so destination is: */
|
||||
relation_to = relation_to->next;
|
||||
}
|
||||
|
||||
/* skip if destination endpoint has NOT audio mode CONNECT */
|
||||
if (relation_to->channel_state != 1)
|
||||
return;
|
||||
|
||||
/* now we may send our data to the endpoint where it
|
||||
* will be delivered to the port
|
||||
*/
|
||||
//printf("from %d, to %d\n", relation_from->epoint_id, relation_to->epoint_id);
|
||||
message_forward(j_serial, relation_to->epoint_id, JOIN_TO_EPOINT, param);
|
||||
}
|
||||
|
||||
/* release join from endpoint
|
||||
* if the join has two relations, all relations are freed and the join will be
|
||||
* destroyed
|
||||
|
@ -651,7 +611,7 @@ void JoinPBX::message_epoint(unsigned int epoint_id, int message_type, union par
|
|||
// joinpbx_debug(join,"Join::message_epoint");
|
||||
// }
|
||||
if (options.deb & DEBUG_JOIN) {
|
||||
if (message_type != MESSAGE_DATA) {
|
||||
if (message_type) {
|
||||
cl = join_first;
|
||||
while(cl) {
|
||||
if (cl->j_type == JOIN_TYPE_PBX)
|
||||
|
@ -772,12 +732,6 @@ void JoinPBX::message_epoint(unsigned int epoint_id, int message_type, union par
|
|||
}
|
||||
return;
|
||||
|
||||
/* audio data */
|
||||
case MESSAGE_DATA:
|
||||
/* now send audio data to the other endpoint */
|
||||
bridge_data(epoint_id, relation, param);
|
||||
return;
|
||||
|
||||
/* relations sends a connect */
|
||||
case MESSAGE_CONNECT:
|
||||
/* outgoing setup type becomes connected */
|
||||
|
|
|
@ -66,7 +66,6 @@ class JoinPBX : public Join
|
|||
int j_partyline_jingle; /* also play jingle on join/leave */
|
||||
|
||||
void bridge(void);
|
||||
void bridge_data(unsigned int epoint_from, struct join_relation *relation_from, union parameter *param);
|
||||
void remove_relation(struct join_relation *relation);
|
||||
struct join_relation *add_relation(void);
|
||||
int out_setup(unsigned int epoint_id, int message, union parameter *param, char *newnumber, char *newkeypad);
|
||||
|
|
66
mISDN.cpp
66
mISDN.cpp
|
@ -141,7 +141,6 @@ PmISDN::PmISDN(int type, mISDNport *mISDNport, char *portname, struct port_setti
|
|||
p_m_echo = 0;
|
||||
p_m_tone = 0;
|
||||
p_m_rxoff = 0;
|
||||
p_m_joindata = 0;
|
||||
p_m_inband_send_on = 0;
|
||||
p_m_inband_receive_on = 0;
|
||||
p_m_dtmf = !mISDNport->ifport->nodtmf;
|
||||
|
@ -1338,7 +1337,7 @@ void PmISDN::load_tx(void)
|
|||
}
|
||||
|
||||
if (p_tone_name[0] || p_m_crypt_msg_loops || p_m_inband_send_on || p_m_load) {
|
||||
schedule_timer(&p_m_loadtimer, 0, ISDN_TRANSMIT*125);
|
||||
schedule_timer(&p_m_loadtimer, 0, PORT_TRANSMIT * 125);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1364,8 +1363,6 @@ static int mISDN_timeout(struct lcr_timer *timer, void *instance, int i)
|
|||
void PmISDN::bchannel_receive(struct mISDNhead *hh, unsigned char *data, int len)
|
||||
{
|
||||
unsigned int cont = *((unsigned int *)data);
|
||||
unsigned char *data_temp;
|
||||
unsigned int length_temp;
|
||||
struct lcr_msg *message;
|
||||
unsigned char *p;
|
||||
int l;
|
||||
|
@ -1488,23 +1485,8 @@ void PmISDN::bchannel_receive(struct mISDNhead *hh, unsigned char *data, int len
|
|||
cryptman_listen_bch(data, len);
|
||||
}
|
||||
|
||||
p = data;
|
||||
|
||||
/* send data to epoint */
|
||||
if (p_m_joindata && ACTIVE_EPOINT(p_epointlist)) { /* only if we have an epoint object */
|
||||
length_temp = len;
|
||||
data_temp = p;
|
||||
while(length_temp) {
|
||||
message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DATA);
|
||||
message->param.data.len = (length_temp>sizeof(message->param.data.data))?sizeof(message->param.data.data):length_temp;
|
||||
memcpy(message->param.data.data, data_temp, message->param.data.len);
|
||||
message_put(message);
|
||||
if (length_temp <= sizeof(message->param.data.data))
|
||||
break;
|
||||
data_temp += sizeof(message->param.data.data);
|
||||
length_temp -= sizeof(message->param.data.data);
|
||||
}
|
||||
}
|
||||
/* send to remote, if bridged */
|
||||
bridge_tx(data, len);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1672,15 +1654,6 @@ void PmISDN::message_mISDNsignal(unsigned int epoint_id, int message_id, union p
|
|||
set_conf(oldconf, newconf);
|
||||
break;
|
||||
|
||||
case mISDNSIGNAL_JOINDATA:
|
||||
if (p_m_joindata != param->mISDNsignal.joindata) {
|
||||
p_m_joindata = param->mISDNsignal.joindata;
|
||||
PDEBUG(DEBUG_BCHANNEL, "we change to joindata=%d.\n", p_m_joindata);
|
||||
update_rxoff();
|
||||
} else
|
||||
PDEBUG(DEBUG_BCHANNEL, "we already have joindata=%d.\n", p_m_joindata);
|
||||
break;
|
||||
|
||||
case mISDNSIGNAL_DELAY:
|
||||
if (p_m_delay != param->mISDNsignal.delay) {
|
||||
p_m_delay = param->mISDNsignal.delay;
|
||||
|
@ -1767,32 +1740,31 @@ void PmISDN::message_crypt(unsigned int epoint_id, int message_id, union paramet
|
|||
*/
|
||||
int PmISDN::message_epoint(unsigned int epoint_id, int message_id, union parameter *param)
|
||||
{
|
||||
if (Port::message_epoint(epoint_id, message_id, param))
|
||||
return(1);
|
||||
if (Port::message_epoint(epoint_id, message_id, param)) {
|
||||
if (message_id == MESSAGE_BRIDGE)
|
||||
update_rxoff();
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch(message_id) {
|
||||
case MESSAGE_DATA: /* tx-data from upper layer */
|
||||
txfromup(param->data.data, param->data.len);
|
||||
return(1);
|
||||
|
||||
case MESSAGE_mISDNSIGNAL: /* user command */
|
||||
PDEBUG(DEBUG_ISDN, "PmISDN(%s) received special ISDN SIGNAL %d.\n", p_name, param->mISDNsignal.message);
|
||||
message_mISDNsignal(epoint_id, message_id, param);
|
||||
return(1);
|
||||
return 1;
|
||||
|
||||
case MESSAGE_CRYPT: /* crypt control command */
|
||||
PDEBUG(DEBUG_ISDN, "PmISDN(%s) received encryption command '%d'.\n", p_name, param->crypt.type);
|
||||
message_crypt(epoint_id, message_id, param);
|
||||
return(1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PmISDN::update_rxoff(void)
|
||||
{
|
||||
/* call bridges in user space OR crypto OR recording */
|
||||
if (p_m_joindata || p_m_crypt_msg_loops || p_m_crypt_listen || p_record || p_m_inband_receive_on) {
|
||||
if (p_bridge || p_m_crypt_msg_loops || p_m_crypt_listen || p_record || p_m_inband_receive_on) {
|
||||
/* rx IS required */
|
||||
if (p_m_rxoff) {
|
||||
/* turn on RX */
|
||||
|
@ -2556,22 +2528,22 @@ void mISDNport_close(struct mISDNport *mISDNport)
|
|||
/*
|
||||
* enque data from upper buffer
|
||||
*/
|
||||
void PmISDN::txfromup(unsigned char *data, int length)
|
||||
int PmISDN::bridge_rx(unsigned char *data, int length)
|
||||
{
|
||||
unsigned char buf[MISDN_HEADER_LEN+((length>ISDN_LOAD)?length:ISDN_LOAD)];
|
||||
struct mISDNhead *hh = (struct mISDNhead *)buf;
|
||||
int ret;
|
||||
|
||||
if (p_m_b_index < 0)
|
||||
return;
|
||||
return -EIO;
|
||||
if (p_m_mISDNport->b_state[p_m_b_index] != B_STATE_ACTIVE)
|
||||
return;
|
||||
return -EINVAL;
|
||||
|
||||
/* check if high priority tones exist
|
||||
* ignore data in this case
|
||||
*/
|
||||
if (p_tone_name[0] || p_m_crypt_msg_loops || p_m_inband_send_on)
|
||||
return;
|
||||
return -EBUSY;
|
||||
|
||||
/* preload procedure
|
||||
* if transmit buffer in DSP module is empty,
|
||||
|
@ -2585,14 +2557,14 @@ void PmISDN::txfromup(unsigned char *data, int length)
|
|||
if (ret <= 0)
|
||||
PERROR("Failed to send to socket %d\n", p_m_mISDNport->b_sock[p_m_b_index].fd);
|
||||
p_m_load += ISDN_LOAD;
|
||||
schedule_timer(&p_m_loadtimer, 0, ISDN_TRANSMIT*125);
|
||||
schedule_timer(&p_m_loadtimer, 0, PORT_TRANSMIT * 125);
|
||||
}
|
||||
|
||||
/* drop if load would exceed ISDN_MAXLOAD
|
||||
* this keeps the delay not too high
|
||||
*/
|
||||
if (p_m_load+length > ISDN_MAXLOAD)
|
||||
return;
|
||||
return -EINVAL;
|
||||
|
||||
/* make and send frame */
|
||||
hh->prim = PH_DATA_REQ;
|
||||
|
@ -2602,6 +2574,8 @@ void PmISDN::txfromup(unsigned char *data, int length)
|
|||
if (ret <= 0)
|
||||
PERROR("Failed to send to socket %d\n", p_m_mISDNport->b_sock[p_m_b_index].fd);
|
||||
p_m_load += length;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PmISDN::inband_send(unsigned char *buffer, int len)
|
||||
|
|
10
mISDN.h
10
mISDN.h
|
@ -132,10 +132,10 @@ class PmISDN : public Port
|
|||
int p_m_mute; /* if set, conf is disconnected */
|
||||
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_txdata; /* get what we transmit */
|
||||
int p_m_dtmf; /* dtmf decoding is enabled */
|
||||
int p_m_joindata; /* the call requires data due to no briging capability */
|
||||
|
||||
int bridge_rx(unsigned char *data, int len);
|
||||
|
||||
struct lcr_timer p_m_loadtimer; /* timer for audio transmission */
|
||||
virtual void update_load(void);
|
||||
|
@ -143,10 +143,6 @@ class PmISDN : public Port
|
|||
int p_m_load; /* current data in dsp tx buffer */
|
||||
unsigned int p_m_last_tv_sec; /* time stamp of last tx_load call, (to sync audio data */
|
||||
unsigned int p_m_last_tv_msec;
|
||||
// int p_m_fromup_buffer_readp; /* buffer for audio from remote endpoint */
|
||||
// int p_m_fromup_buffer_writep;
|
||||
// unsigned char p_m_fromup_buffer[FROMUP_BUFFER_SIZE];
|
||||
void txfromup(unsigned char *data, int length);
|
||||
|
||||
int p_m_crypt; /* encryption is enabled */
|
||||
int p_m_crypt_msg_loops; /* sending a message */
|
||||
|
@ -171,8 +167,6 @@ class PmISDN : public Port
|
|||
int p_m_b_channel; /* number 1,2 1..15,17... */
|
||||
int p_m_b_exclusive; /* if bchannel is exclusive */
|
||||
int p_m_b_reserve; /* set if channel is reserved */
|
||||
// long long p_m_jittercheck; /* time of audio data */
|
||||
// long long p_m_jitterdropped; /* number of bytes dropped */
|
||||
int p_m_b_mode; /* bchannel mode */
|
||||
int p_m_hold; /* if port is on hold */
|
||||
struct lcr_timer p_m_timeout; /* timeout of timers */
|
||||
|
|
16
macro.h
16
macro.h
|
@ -63,9 +63,9 @@ static inline void sprint(char *dst, unsigned int siz, const char *fmt, ...)
|
|||
#define UNPRINT snprintf
|
||||
#define VUNPRINT vsnprintf
|
||||
|
||||
#define FATAL(fmt, arg...) _fatal(__FILE__, __FUNCTION__, __LINE__, fmt, ##arg)
|
||||
/* fatal error with error message and exit */
|
||||
#define FATAL(fmt, arg...) fatal(__FUNCTION__, __LINE__, fmt, ##arg)
|
||||
static inline void fatal(const char *function, int line, const char *fmt, ...)
|
||||
static inline void _fatal(const char *file, const char *function, int line, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
char buffer[256];
|
||||
|
@ -74,23 +74,23 @@ static inline void fatal(const char *function, int line, const char *fmt, ...)
|
|||
vsnprintf(buffer, sizeof(buffer), fmt, args);
|
||||
va_end(args);
|
||||
buffer[sizeof(buffer)-1] = '\0';
|
||||
fprintf(stderr, "FATAL ERROR in function %s, line %d: %s", function, line, buffer);
|
||||
fprintf(stderr, "FATAL ERROR in function %s/%s, line %d: %s", file, function, line, buffer);
|
||||
fprintf(stderr, "This error is not recoverable, must exit here.\n");
|
||||
#ifdef DEBUG_FUNC
|
||||
debug(function, line, "FATAL", buffer);
|
||||
debug(function, line, "FATAL", (char *)"This error is not recoverable, must exit here.\n");
|
||||
debug(file, function, line, "FATAL", buffer);
|
||||
debug(file, function, line, "FATAL", (char *)"This error is not recoverable, must exit here.\n");
|
||||
#endif
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* memory allocation with setting to zero */
|
||||
#define MALLOC(size) _malloc(size, __FUNCTION__, __LINE__)
|
||||
static inline void *_malloc(unsigned int size, const char *function, int line)
|
||||
#define MALLOC(size) _malloc(size, __FILE__, __FUNCTION__, __LINE__)
|
||||
static inline void *_malloc(unsigned int size, const char *file, const char *function, int line)
|
||||
{
|
||||
void *addr;
|
||||
addr = malloc(size);
|
||||
if (!addr)
|
||||
fatal(function, line, "No memory for %d bytes.\n", size);
|
||||
_fatal(file, function, line, "No memory for %d bytes.\n", size);
|
||||
memset(addr, 0, size);
|
||||
return addr;
|
||||
}
|
||||
|
|
23
main.c
23
main.c
|
@ -53,7 +53,7 @@ int last_debug = 0;
|
|||
int debug_newline = 1;
|
||||
int nooutput = 0;
|
||||
|
||||
void debug(const char *function, int line, const char *prefix, char *buffer)
|
||||
void debug(const char *file, const char *function, int line, const char *prefix, char *buffer)
|
||||
{
|
||||
time_t now;
|
||||
struct tm *now_tm;
|
||||
|
@ -73,7 +73,7 @@ void debug(const char *function, int line, const char *prefix, char *buffer)
|
|||
if (debug_newline)
|
||||
printf("\033[32m%06d %s\033[37m%s", debug_count%1000000, prefix?prefix:"", prefix?" ":"");
|
||||
if (function)
|
||||
printf("(in %s() line %d): %s", function, line, buffer);
|
||||
printf("(in %s/%s() line %d): %s", file, function, line, buffer);
|
||||
else
|
||||
printf("%s", buffer);
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ void debug(const char *function, int line, const char *prefix, char *buffer)
|
|||
}
|
||||
|
||||
|
||||
void _printdebug(const char *function, int line, unsigned int mask, const char *fmt, ...)
|
||||
void _printdebug(const char *file, const char *function, int line, unsigned int mask, const char *fmt, ...)
|
||||
{
|
||||
char buffer[4096];
|
||||
va_list args;
|
||||
|
@ -109,12 +109,12 @@ void _printdebug(const char *function, int line, unsigned int mask, const char *
|
|||
buffer[sizeof(buffer)-1]=0;
|
||||
va_end(args);
|
||||
|
||||
debug(function, line, "DEBUG", buffer);
|
||||
debug(file, function, line, "DEBUG", buffer);
|
||||
|
||||
pthread_mutex_unlock(&mutexd);
|
||||
}
|
||||
|
||||
void _printerror(const char *function, int line, const char *fmt, ...)
|
||||
void _printerror(const char *file, const char *function, int line, const char *fmt, ...)
|
||||
{
|
||||
char buffer[4096];
|
||||
va_list args;
|
||||
|
@ -127,7 +127,7 @@ void _printerror(const char *function, int line, const char *fmt, ...)
|
|||
va_end(args);
|
||||
|
||||
if (options.deb)
|
||||
debug(function, line, "ERROR", buffer);
|
||||
debug(file, function, line, "ERROR", buffer);
|
||||
else { /* only if we do not debug */
|
||||
if (function)
|
||||
fprintf(stderr, "ERROR (in %s() line %d) %s", function, line, buffer);
|
||||
|
@ -182,7 +182,7 @@ int main(int argc, char *argv[])
|
|||
struct sched_param schedp;
|
||||
int created_mutexd = 0,/* created_mutext = 0,*/ created_mutexe = 0,
|
||||
created_lock = 0, created_signal = 0, created_debug = 0,
|
||||
created_misdn = 0;
|
||||
created_misdn = 0, created_message = 0;
|
||||
char tracetext[256], lock[128];
|
||||
char options_error[256];
|
||||
int polling = 0;
|
||||
|
@ -457,6 +457,7 @@ init is done when interface is up
|
|||
|
||||
/* init message */
|
||||
init_message();
|
||||
created_message = 1;
|
||||
|
||||
/*** main loop ***/
|
||||
SPRINT(tracetext, "%s %s started, waiting for calls...", NAME, VERSION_STRING);
|
||||
|
@ -506,9 +507,6 @@ init is done when interface is up
|
|||
end_trace();
|
||||
ret=0;
|
||||
|
||||
/* clean messacleane */
|
||||
cleanup_message();
|
||||
|
||||
/* free all */
|
||||
free:
|
||||
|
||||
|
@ -528,7 +526,6 @@ free:
|
|||
}
|
||||
|
||||
/* destroy objects */
|
||||
|
||||
while(port_first) {
|
||||
debug_count++;
|
||||
delete port_first;
|
||||
|
@ -560,6 +557,10 @@ free:
|
|||
PDEBUG(DEBUG_MSG, "freed %d pending messages\n", i);
|
||||
}
|
||||
|
||||
/* clean messages */
|
||||
if (created_message)
|
||||
cleanup_message();
|
||||
|
||||
/* free tones */
|
||||
if (toneset_first)
|
||||
free_tones();
|
||||
|
|
14
main.h
14
main.h
|
@ -51,14 +51,14 @@ extern int fhuse;
|
|||
|
||||
extern FILE *debug_fp;
|
||||
|
||||
#define PDEBUG(mask, fmt, arg...) _printdebug(__FUNCTION__, __LINE__, mask, fmt, ## arg)
|
||||
#define PERROR(fmt, arg...) _printerror(__FUNCTION__, __LINE__, fmt, ## arg)
|
||||
#define PDEBUG_RUNTIME(mask, fmt, arg...) _printdebug(NULL, 0, mask, fmt, ## arg)
|
||||
#define PERROR_RUNTIME(fmt, arg...) _printerror(NULL, 0, fmt, ## arg)
|
||||
void _printdebug(const char *function, int line, unsigned int mask, const char *fmt, ...);
|
||||
void _printerror(const char *function, int line, const char *fmt, ...);
|
||||
#define PDEBUG(mask, fmt, arg...) _printdebug(__FILE__, __FUNCTION__, __LINE__, mask, fmt, ## arg)
|
||||
#define PERROR(fmt, arg...) _printerror(__FILE__, __FUNCTION__, __LINE__, fmt, ## arg)
|
||||
#define PDEBUG_RUNTIME(mask, fmt, arg...) _printdebug(NULL, NULL, 0, mask, fmt, ## arg)
|
||||
#define PERROR_RUNTIME(fmt, arg...) _printerror(NULL, NULL, 0, fmt, ## arg)
|
||||
void _printdebug(const char *file, const char *function, int line, unsigned int mask, const char *fmt, ...);
|
||||
void _printerror(const char *file, const char *function, int line, const char *fmt, ...);
|
||||
#define DEBUG_FUNC
|
||||
void debug(const char *function, int line, const char *prefix, char *buffer);
|
||||
void debug(const char *file, const char *function, int line, const char *prefix, char *buffer);
|
||||
|
||||
#define DEBUG_CONFIG 0x0001
|
||||
#define DEBUG_MSG 0x0002
|
||||
|
|
|
@ -49,7 +49,7 @@ struct lcr_msg *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 lcr_msg *message)
|
||||
void _message_put(struct lcr_msg *message, const char *file, int line)
|
||||
{
|
||||
if (message->id_to == 0) {
|
||||
PDEBUG(DEBUG_MSG, "message %s not written, because destination is 0.\n", messages_txt[message->type]);
|
||||
|
@ -57,8 +57,8 @@ void message_put(struct lcr_msg *message)
|
|||
return;
|
||||
}
|
||||
|
||||
if ((options.deb&DEBUG_MSG) && message->type != MESSAGE_DATA)
|
||||
PDEBUG(DEBUG_MSG, "message %s written from %ld to %ld (memory %x)\n", messages_txt[message->type], message->id_from, message->id_to, message);
|
||||
if ((options.deb & DEBUG_MSG))
|
||||
PDEBUG(DEBUG_MSG, "message %s written from %ld to %ld (memory %x at file %s, line %d)\n", messages_txt[message->type], message->id_from, message->id_to, message, file, line);
|
||||
|
||||
*messagepointer_end = message;
|
||||
messagepointer_end = &(message->next);
|
||||
|
@ -102,8 +102,7 @@ struct lcr_msg *message_get(void)
|
|||
|
||||
message->keep = 0;
|
||||
|
||||
if ((options.deb&DEBUG_MSG) && message->type != MESSAGE_DATA)
|
||||
|
||||
if ((options.deb & DEBUG_MSG))
|
||||
PDEBUG(DEBUG_MSG, "message %s reading from %ld to %ld (memory %x)\n", messages_txt[message->type], message->id_from, message->id_to, message);
|
||||
|
||||
return(message);
|
||||
|
|
20
message.h
20
message.h
|
@ -122,7 +122,6 @@ enum { /* diversion types */
|
|||
enum { /* isdnsignal */
|
||||
mISDNSIGNAL_VOLUME, /* change volume */
|
||||
mISDNSIGNAL_CONF, /* joint/split conference */
|
||||
mISDNSIGNAL_JOINDATA, /* data required by join instance */
|
||||
mISDNSIGNAL_ECHO, /* enable/disable echoe */
|
||||
mISDNSIGNAL_DELAY, /* use delay or adaptive jitter */
|
||||
};
|
||||
|
@ -277,13 +276,6 @@ struct park_info {
|
|||
int len;
|
||||
};
|
||||
|
||||
#define ISDN_TRANSMIT 256
|
||||
/* DATA */
|
||||
struct param_data {
|
||||
unsigned char data[ISDN_TRANSMIT]; /* audio data */
|
||||
int len; /* audio data */
|
||||
};
|
||||
|
||||
struct param_play {
|
||||
char file[512]; /* file name */
|
||||
int offset; /* offset to start file at (in seconds) */
|
||||
|
@ -304,7 +296,6 @@ struct param_mISDNsignal {
|
|||
int tx_gain;
|
||||
int rx_gain;
|
||||
int conf;
|
||||
int joindata;
|
||||
int tone;
|
||||
int echo;
|
||||
int delay;
|
||||
|
@ -352,7 +343,6 @@ union parameter {
|
|||
int state; /* MESSAGE_TIMEOUT */
|
||||
int knock; /* MESSAGE_KNOCK 0=off !0=on */
|
||||
int audiopath; /* MESSAGE_audiopath see RELATION_CHANNEL_* (join.h) */
|
||||
struct param_data data; /* MESSAGE_DATA */
|
||||
struct param_play play; /* MESSAGE_VBOX_PLAY */
|
||||
int speed; /* MESSAGE_VBOX_PLAY_SPEED */
|
||||
struct param_counter counter; /* MESSAGE_TONE_COUNTER */
|
||||
|
@ -362,6 +352,7 @@ union parameter {
|
|||
struct param_hello hello; /* MESSAGE_HELLO */
|
||||
struct param_bchannel bchannel; /* MESSAGE_BCHANNEL */
|
||||
struct param_newref newref; /* MESSAGE_NEWREF */
|
||||
unsigned int bridge_id; /* MESSAGE_BRIDGE */
|
||||
};
|
||||
|
||||
enum { /* message flow */
|
||||
|
@ -403,11 +394,9 @@ enum { /* messages between entities */
|
|||
MESSAGE_SUSPEND, /* suspend port */
|
||||
MESSAGE_RESUME, /* resume port */
|
||||
MESSAGE_AUDIOPATH, /* set status of audio path to endpoint (to call, audio is also set) */
|
||||
// MESSAGE_REMOTE_AUDIO, /* tell remote to set audio status */
|
||||
MESSAGE_PATTERN, /* pattern information tones available */
|
||||
MESSAGE_NOPATTERN, /* pattern information tones unavailable */
|
||||
MESSAGE_CRYPT, /* encryption message */
|
||||
MESSAGE_DATA, /* audio/hdlc data */
|
||||
MESSAGE_VBOX_PLAY, /* play recorded file */
|
||||
MESSAGE_VBOX_PLAY_SPEED,/* change speed of file */
|
||||
MESSAGE_VBOX_TONE, /* set answering VBOX tone */
|
||||
|
@ -416,6 +405,7 @@ enum { /* messages between entities */
|
|||
MESSAGE_BCHANNEL, /* request/assign/remove bchannel */
|
||||
MESSAGE_HELLO, /* hello message for remote application */
|
||||
MESSAGE_NEWREF, /* special message to create and inform ref */
|
||||
MESSAGE_BRIDGE, /* control port bridge */
|
||||
};
|
||||
|
||||
#define MESSAGES static const char *messages_txt[] = { \
|
||||
|
@ -439,11 +429,9 @@ enum { /* messages between entities */
|
|||
"MESSAGE_SUSPEND", \
|
||||
"MESSAGE_RESUME", \
|
||||
"MESSAGE_AUDIOPATH", \
|
||||
/* "MESSAGE_REMOTE_AUDIO",*/ \
|
||||
"MESSAGE_PATTERN", \
|
||||
"MESSAGE_NOPATTERN", \
|
||||
"MESSAGE_CRYPT", \
|
||||
"MESSAGE_DATA", \
|
||||
"MESSAGE_VBOX_PLAY", \
|
||||
"MESSAGE_VBOX_PLAY_SPEED", \
|
||||
"MESSAGE_VBOX_TONE", \
|
||||
|
@ -452,11 +440,13 @@ enum { /* messages between entities */
|
|||
"MESSAGE_BCHANNEL", \
|
||||
"MESSAGE_HELLO", \
|
||||
"MESSAGE_NEWREF", \
|
||||
"MESSAGE_BRIDGE", \
|
||||
};
|
||||
|
||||
|
||||
struct lcr_msg *message_create(int id_from, int id_to, int flow, int type);
|
||||
void message_put(struct lcr_msg *message);
|
||||
#define message_put(m) _message_put(m, __FILE__, __LINE__)
|
||||
void _message_put(struct lcr_msg *message, const char *file, int line);
|
||||
struct lcr_msg *message_forward(int id_from, int id_to, int flow, union parameter *param);
|
||||
struct lcr_msg *message_get(void);
|
||||
void message_free(struct lcr_msg *message);
|
||||
|
|
167
port.cpp
167
port.cpp
|
@ -54,6 +54,9 @@ class Port *port_first = NULL;
|
|||
|
||||
unsigned int port_serial = 1; /* must be 1, because 0== no port */
|
||||
|
||||
struct port_bridge *p_bridge_first;
|
||||
|
||||
static void remove_bridge(struct port_bridge *bridge, class Port *port);
|
||||
|
||||
/* free epointlist relation
|
||||
*/
|
||||
|
@ -146,7 +149,7 @@ Port::Port(int type, const char *portname, struct port_settings *settings)
|
|||
{
|
||||
class Port *temp, **tempp;
|
||||
|
||||
PDEBUG(DEBUG_PORT, "new port of type %d, name '%s'\n", type, portname);
|
||||
PDEBUG(DEBUG_PORT, "new port of type 0x%x, name '%s'\n", type, portname);
|
||||
|
||||
/* initialize object */
|
||||
if (settings)
|
||||
|
@ -169,6 +172,7 @@ Port::Port(int type, const char *portname, struct port_settings *settings)
|
|||
memset(&p_redirinfo, 0, sizeof(p_redirinfo));
|
||||
memset(&p_capainfo, 0, sizeof(p_capainfo));
|
||||
p_echotest = 0;
|
||||
p_bridge = 0;
|
||||
|
||||
/* call recording */
|
||||
p_record = NULL;
|
||||
|
@ -202,13 +206,18 @@ Port::~Port(void)
|
|||
class Port *temp, **tempp;
|
||||
struct lcr_msg *message;
|
||||
|
||||
PDEBUG(DEBUG_PORT, "removing port of type 0x%x, name '%s'\n", p_type, p_name);
|
||||
|
||||
if (p_bridge) {
|
||||
PDEBUG(DEBUG_PORT, "Removing us from bridge %u\n", p_bridge->bridge_id);
|
||||
remove_bridge(p_bridge, this);
|
||||
}
|
||||
|
||||
if (p_record)
|
||||
close_record(0, 0);
|
||||
|
||||
classuse--;
|
||||
|
||||
PDEBUG(DEBUG_PORT, "removing port of type %d, name '%s'\n", p_type, p_name);
|
||||
|
||||
/* disconnect port from endpoint */
|
||||
while(p_epointlist) {
|
||||
/* send disconnect */
|
||||
|
@ -589,38 +598,42 @@ try_loop:
|
|||
}
|
||||
|
||||
|
||||
/* endpoint sends messages to the port
|
||||
* this is called by the message_epoint inherited by child classes
|
||||
* therefor a return=1 means: stop, no more processing
|
||||
/* Endpoint sends messages to the port
|
||||
* This is called by the message_epoint, inherited by child classes.
|
||||
* Therefor a return 1 means: "already handled here"
|
||||
*/
|
||||
//extern struct lcr_msg *dddebug;
|
||||
int Port::message_epoint(unsigned int epoint_id, int message_id, union parameter *param)
|
||||
{
|
||||
/* check if we got audio data from one remote port */
|
||||
switch(message_id) {
|
||||
case MESSAGE_TONE: /* play tone */
|
||||
PDEBUG(DEBUG_PORT, "PORT(%s) isdn port with (caller id %s) setting tone '%s' dir '%s'\n", p_name, p_callerinfo.id, param->tone.name, param->tone.dir);
|
||||
case MESSAGE_TONE: /* play tone */
|
||||
PDEBUG(DEBUG_PORT, "PORT(%s) setting tone '%s' dir '%s'\n", p_name, param->tone.name, param->tone.dir);
|
||||
set_tone(param->tone.dir,param->tone.name);
|
||||
return(1);
|
||||
return 1;
|
||||
|
||||
case MESSAGE_VBOX_TONE: /* play tone of answering machine */
|
||||
case MESSAGE_VBOX_TONE: /* play tone of answering machine */
|
||||
PDEBUG(DEBUG_PORT, "PORT(%s) set answering machine tone '%s' '%s'\n", p_name, param->tone.dir, param->tone.name);
|
||||
set_vbox_tone(param->tone.dir, param->tone.name);
|
||||
return(1);
|
||||
return 1;
|
||||
|
||||
case MESSAGE_VBOX_PLAY: /* play recording of answering machine */
|
||||
case MESSAGE_VBOX_PLAY: /* play recording of answering machine */
|
||||
PDEBUG(DEBUG_PORT, "PORT(%s) set answering machine file to play '%s' (offset %d seconds)\n", p_name, param->play.file, param->play.offset);
|
||||
set_vbox_play(param->play.file, param->play.offset);
|
||||
return(1);
|
||||
return 1;
|
||||
|
||||
case MESSAGE_VBOX_PLAY_SPEED: /* set speed of playback (recording of answering machine) */
|
||||
case MESSAGE_VBOX_PLAY_SPEED: /* set speed of playback (recording of answering machine) */
|
||||
PDEBUG(DEBUG_PORT, "PORT(%s) set answering machine playback speed %d (times)\n", p_name, param->speed);
|
||||
set_vbox_speed(param->speed);
|
||||
return(1);
|
||||
return 1;
|
||||
|
||||
case MESSAGE_BRIDGE: /* create / join / leave / destroy bridge */
|
||||
PDEBUG(DEBUG_PORT, "PORT(%s) bridging to id %d\n", p_name, param->bridge_id);
|
||||
bridge(param->bridge_id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1154,3 +1167,125 @@ void Port::update_load(void)
|
|||
{
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* bridge handling
|
||||
*/
|
||||
|
||||
static void remove_bridge(struct port_bridge *bridge, class Port *port)
|
||||
{
|
||||
struct port_bridge **temp = &p_bridge_first;
|
||||
while (*temp) {
|
||||
if (*temp == bridge) {
|
||||
int remove = 0;
|
||||
|
||||
/* Remove us from bridge. If bridge is empty, remove it completely. */
|
||||
if (bridge->sunrise == port) {
|
||||
bridge->sunrise = NULL;
|
||||
if (!bridge->sunset)
|
||||
remove = 1;
|
||||
}
|
||||
if (bridge->sunset == port) {
|
||||
bridge->sunset = NULL;
|
||||
if (!bridge->sunrise)
|
||||
remove = 1;
|
||||
}
|
||||
if (remove) {
|
||||
PDEBUG(DEBUG_PORT, "Remove bridge %u\n", bridge->bridge_id);
|
||||
*temp = bridge->next;
|
||||
FREE(bridge, sizeof(struct port_bridge));
|
||||
memuse--;
|
||||
}
|
||||
return;
|
||||
}
|
||||
temp = &((*temp)->next);
|
||||
}
|
||||
PERROR("Bridge %p not found in list\n", bridge);
|
||||
}
|
||||
|
||||
void Port::bridge(unsigned int bridge_id)
|
||||
{
|
||||
/* Remove bridge, if we leave bridge or if we join a different bridge. */
|
||||
if (p_bridge && bridge_id != p_bridge->bridge_id) {
|
||||
PDEBUG(DEBUG_PORT, "Remove port %u from bridge %u, because out new bridge is %u\n", p_serial, p_bridge->bridge_id, bridge_id);
|
||||
remove_bridge(p_bridge, this);
|
||||
p_bridge = NULL;
|
||||
}
|
||||
|
||||
/* if we leave bridge */
|
||||
if (!bridge_id)
|
||||
return;
|
||||
|
||||
/* find bridge */
|
||||
if (!p_bridge) {
|
||||
struct port_bridge *temp = p_bridge_first;
|
||||
|
||||
while (temp) {
|
||||
if (temp->bridge_id == bridge_id)
|
||||
break;
|
||||
temp = temp->next;
|
||||
}
|
||||
p_bridge = temp;
|
||||
if (p_bridge)
|
||||
PDEBUG(DEBUG_PORT, "Port %d found existing bridge %u.\n", p_serial, p_bridge->bridge_id);
|
||||
}
|
||||
|
||||
/* create bridge */
|
||||
if (!p_bridge) {
|
||||
struct port_bridge **temp = &p_bridge_first;
|
||||
|
||||
p_bridge = (struct port_bridge *) MALLOC(sizeof(struct port_bridge));
|
||||
memuse++;
|
||||
p_bridge->bridge_id = bridge_id;
|
||||
p_bridge->sunrise = this;
|
||||
|
||||
/* attach bridge instance to list */
|
||||
while (*temp)
|
||||
temp = &((*temp)->next);
|
||||
*temp = p_bridge;
|
||||
PDEBUG(DEBUG_PORT, "Port %d creating not existing bridge %u.\n", p_serial, p_bridge->bridge_id);
|
||||
}
|
||||
|
||||
/* already joined */
|
||||
if (p_bridge->sunrise == this || p_bridge->sunset == this)
|
||||
return;
|
||||
|
||||
/* join bridge */
|
||||
if (!p_bridge->sunrise) {
|
||||
p_bridge->sunrise = this;
|
||||
return;
|
||||
}
|
||||
if (!p_bridge->sunset) {
|
||||
p_bridge->sunset = this;
|
||||
return;
|
||||
}
|
||||
|
||||
PERROR("Bridge ID %u cannot be joined by port %u, because it is already occupied by ports %u and %u.\n", p_bridge->bridge_id, p_serial, p_bridge->sunrise->p_serial, p_bridge->sunset->p_serial);
|
||||
p_bridge = NULL;
|
||||
}
|
||||
|
||||
/* send data to remote Port */
|
||||
int Port::bridge_tx(unsigned char *data, int len)
|
||||
{
|
||||
class Port *to_port = NULL;
|
||||
|
||||
/* get remote port from bridge */
|
||||
if (!p_bridge)
|
||||
return -EINVAL;
|
||||
if (p_bridge->sunrise == this)
|
||||
to_port = p_bridge->sunset;
|
||||
if (p_bridge->sunset == this)
|
||||
to_port = p_bridge->sunrise;
|
||||
if (!to_port)
|
||||
return -EINVAL;
|
||||
|
||||
// printf("Traffic: %u -> %u (bridge %u)\n", p_serial, to_port->p_serial, p_bridge->bridge_id);
|
||||
return to_port->bridge_rx(data, len);
|
||||
}
|
||||
|
||||
/* receive data from remote Port (dummy, needs to be inherited) */
|
||||
int Port::bridge_rx(unsigned char *data, int len)
|
||||
{
|
||||
return 0; /* datenklo */
|
||||
}
|
||||
|
||||
|
|
18
port.h
18
port.h
|
@ -111,6 +111,8 @@ enum { /* event list from listening to tty */
|
|||
#define RECORD_BUFFER_LENGTH 1024 // must be a binary border & must be greater 256, because 256 will be written if buffer overflows
|
||||
#define RECORD_BUFFER_MASK 1023
|
||||
|
||||
#define PORT_TRANSMIT 256 // how much to transmit via bridge, if it is not defined by received data length
|
||||
|
||||
/* structure of epoint_list */
|
||||
struct epoint_list {
|
||||
struct epoint_list *next;
|
||||
|
@ -147,6 +149,16 @@ struct port_settings {
|
|||
int no_seconds;
|
||||
};
|
||||
|
||||
/* port bridge instance */
|
||||
struct port_bridge {
|
||||
struct port_bridge *next; /* next bridge node */
|
||||
unsigned int bridge_id; /* unique ID to identify bridge */
|
||||
class Port *sunrise; /* one side of the bridge */
|
||||
class Port *sunset; /* other side of the bridge */
|
||||
};
|
||||
|
||||
extern struct port_bridge *p_bridge_first;
|
||||
|
||||
/* generic port class */
|
||||
class Port
|
||||
{
|
||||
|
@ -189,6 +201,12 @@ class Port
|
|||
/* endpoint relation */
|
||||
struct epoint_list *p_epointlist; /* endpoint relation */
|
||||
|
||||
/* audio bridging */
|
||||
struct port_bridge *p_bridge; /* linked to a port bridge or NULL */
|
||||
void bridge(unsigned int bridge_id); /* join a bridge */
|
||||
int bridge_tx(unsigned char *data, int len); /* used to transmit data to remote port */
|
||||
virtual int bridge_rx(unsigned char *data, int len); /* function to be inherited, so data is received */
|
||||
|
||||
/* state */
|
||||
int p_state; /* state of port */
|
||||
void new_state(int state); /* set new state */
|
||||
|
|
4
select.c
4
select.c
|
@ -371,10 +371,10 @@ void _del_work(struct lcr_work *work, const char *func)
|
|||
#endif
|
||||
}
|
||||
|
||||
void trigger_work(struct lcr_work *work)
|
||||
void _trigger_work(struct lcr_work *work, const char *func)
|
||||
{
|
||||
if (!work->inuse) {
|
||||
FATAL("Work not added\n");
|
||||
FATAL("Work not added, (called from func %s)\n", func);
|
||||
}
|
||||
|
||||
/* event already triggered */
|
||||
|
|
3
select.h
3
select.h
|
@ -57,6 +57,7 @@ struct lcr_work {
|
|||
int _add_work(struct lcr_work *work, int (*cb)(struct lcr_work *work, void *instance, int index), void *instance, int index, const char *func);
|
||||
#define del_work(a) _del_work(a, __func__);
|
||||
void _del_work(struct lcr_work *work, const char *func);
|
||||
void trigger_work(struct lcr_work *work);
|
||||
#define trigger_work(a) _trigger_work(a, __func__);
|
||||
void _trigger_work(struct lcr_work *work, const char *func);
|
||||
|
||||
|
||||
|
|
17
sip.cpp
17
sip.cpp
|
@ -1078,18 +1078,15 @@ int Psip::message_epoint(unsigned int epoint_id, int message_id, union parameter
|
|||
class Endpoint *epoint;
|
||||
|
||||
if (PmISDN::message_epoint(epoint_id, message_id, param))
|
||||
return(1);
|
||||
return 1;
|
||||
|
||||
epoint = find_epoint_id(epoint_id);
|
||||
if (!epoint) {
|
||||
PDEBUG(DEBUG_SIP, "PORT(%s) no endpoint object found where the message is from.\n", p_name);
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch(message_id) {
|
||||
case MESSAGE_DATA:
|
||||
return(1);
|
||||
|
||||
case MESSAGE_ALERTING: /* call is ringing on LCR side */
|
||||
if (p_state != PORT_STATE_IN_SETUP
|
||||
&& p_state != PORT_STATE_IN_PROCEEDING)
|
||||
|
@ -1099,7 +1096,7 @@ int Psip::message_epoint(unsigned int epoint_id, int message_id, union parameter
|
|||
add_trace("respond", "value", "180 Ringing");
|
||||
end_trace();
|
||||
new_state(PORT_STATE_IN_ALERTING);
|
||||
return(1);
|
||||
return 1;
|
||||
|
||||
case MESSAGE_CONNECT: /* call is connected on LCR side */
|
||||
if (p_state != PORT_STATE_IN_SETUP
|
||||
|
@ -1107,22 +1104,22 @@ int Psip::message_epoint(unsigned int epoint_id, int message_id, union parameter
|
|||
&& p_state != PORT_STATE_IN_ALERTING)
|
||||
return 0;
|
||||
message_connect(epoint_id, message_id, param);
|
||||
return(1);
|
||||
return 1;
|
||||
|
||||
case MESSAGE_DISCONNECT: /* call has been disconnected */
|
||||
case MESSAGE_RELEASE: /* call has been released */
|
||||
message_release(epoint_id, message_id, param);
|
||||
return(1);
|
||||
return 1;
|
||||
|
||||
case MESSAGE_SETUP: /* dial-out command received from epoint */
|
||||
message_setup(epoint_id, message_id, param);
|
||||
return(1);
|
||||
return 1;
|
||||
|
||||
default:
|
||||
PDEBUG(DEBUG_SIP, "PORT(%s) SP port with (caller id %s) received an unsupported message: %d\n", p_name, p_callerinfo.id, message_id);
|
||||
}
|
||||
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Psip::parse_sdp(sip_t const *sip, unsigned int *ip, unsigned short *port)
|
||||
|
|
2
trace.c
2
trace.c
|
@ -274,7 +274,7 @@ void _end_trace(const char *__file, int __line)
|
|||
if (string) {
|
||||
/* process debug */
|
||||
if (options.deb)
|
||||
debug(NULL, 0, "TRACE", string);
|
||||
debug(NULL, NULL, 0, "TRACE", string);
|
||||
/* process log */
|
||||
if (options.log[0]) {
|
||||
fp = fopen(options.log, "a");
|
||||
|
|
22
vbox.cpp
22
vbox.cpp
|
@ -103,7 +103,7 @@ void VBoxPort::send_announcement(void)
|
|||
{
|
||||
struct lcr_msg *message;
|
||||
unsigned int tosend;
|
||||
unsigned char buffer[ISDN_TRANSMIT];
|
||||
unsigned char buffer[PORT_TRANSMIT + PORT_TRANSMIT]; /* use twice of the buffer, so we can send more in case of delayed main loop execution */
|
||||
class Endpoint *epoint;
|
||||
int temp;
|
||||
struct timeval current_time;
|
||||
|
@ -118,7 +118,7 @@ void VBoxPort::send_announcement(void)
|
|||
|
||||
/* set time the first time */
|
||||
if (!p_vbox_audio_start)
|
||||
p_vbox_audio_start = now - ISDN_TRANSMIT;
|
||||
p_vbox_audio_start = now - PORT_TRANSMIT;
|
||||
|
||||
/* calculate the number of bytes */
|
||||
tosend = (unsigned int)(now - p_vbox_audio_start) - p_vbox_audio_transferred;
|
||||
|
@ -126,7 +126,7 @@ void VBoxPort::send_announcement(void)
|
|||
tosend = sizeof(buffer);
|
||||
|
||||
/* schedule next event */
|
||||
temp = ISDN_TRANSMIT + ISDN_TRANSMIT - tosend;
|
||||
temp = PORT_TRANSMIT + PORT_TRANSMIT - tosend;
|
||||
if (temp < 0)
|
||||
temp = 0;
|
||||
schedule_timer(&p_vbox_announce_timer, 0, temp*125);
|
||||
|
@ -184,13 +184,17 @@ void VBoxPort::send_announcement(void)
|
|||
} else {
|
||||
if (p_record)
|
||||
record(buffer, tosend, 0); // from down
|
||||
message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DATA);
|
||||
message->param.data.len = tosend;
|
||||
memcpy(message->param.data.data, buffer, tosend);
|
||||
message_put(message);
|
||||
/* send to remote, if bridged */
|
||||
bridge_tx(buffer, tosend);
|
||||
}
|
||||
}
|
||||
|
||||
int VBoxPort::bridge_rx(unsigned char *data, int len)
|
||||
{
|
||||
if (p_record)
|
||||
record(data, len, 1); // from up
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* endpoint sends messages to the vbox port
|
||||
|
@ -211,10 +215,6 @@ int VBoxPort::message_epoint(unsigned int epoint_id, int message_id, union param
|
|||
}
|
||||
|
||||
switch(message_id) {
|
||||
case MESSAGE_DATA:
|
||||
record(param->data.data, param->data.len, 1); // from up
|
||||
return(1);
|
||||
|
||||
case MESSAGE_DISCONNECT: /* call has been disconnected */
|
||||
new_state(PORT_STATE_OUT_DISCONNECT);
|
||||
vbox_trace_header(this, "DISCONNECT to VBox", DIRECTION_OUT);
|
||||
|
|
2
vbox.h
2
vbox.h
|
@ -18,6 +18,8 @@ class VBoxPort : public Port
|
|||
int message_epoint(unsigned int epoint_id, int message, union parameter *param);
|
||||
void send_announcement(void);
|
||||
|
||||
int bridge_rx(unsigned char *data, int len);
|
||||
|
||||
private:
|
||||
struct EndpointAppPBX *p_vbox_apppbx; /* pbx application */
|
||||
unsigned int p_vbox_timeout; /* timeout for recording */
|
||||
|
|
Loading…
Reference in New Issue