alpha phase is open, this means:

it compiles!
it runs!
it calls without known bug yet!

comments to jolly@eversberg.eu
This commit is contained in:
Super User 2007-07-17 19:28:09 +02:00
parent a54078ccf0
commit 5a22e57828
39 changed files with 1032 additions and 2891 deletions

View File

@ -124,14 +124,14 @@ endpointapp.o: endpointapp.cpp *.h Makefile
apppbx.o: apppbx.cpp *.h Makefile
$(CC) -c $(CFLAGS) apppbx.cpp -o apppbx.o
call.o: call.cpp *.h Makefile
$(CC) -c $(CFLAGS) call.cpp -o call.o
join.o: join.cpp *.h Makefile
$(CC) -c $(CFLAGS) join.cpp -o join.o
callpbx.o: callpbx.cpp *.h Makefile
$(CC) -c $(CFLAGS) callpbx.cpp -o callpbx.o
joinpbx.o: joinpbx.cpp *.h Makefile
$(CC) -c $(CFLAGS) joinpbx.cpp -o joinpbx.o
callasterisk.o: callasterisk.cpp *.h Makefile
$(CC) -c $(CFLAGS) callasterisk.cpp -o callasterisk.o
joinasterisk.o: joinasterisk.cpp *.h Makefile
$(CC) -c $(CFLAGS) joinasterisk.cpp -o joinasterisk.o
cause.o: cause.c *.h Makefile
$(CC) -c $(CFLAGS) cause.c -o cause.o
@ -180,9 +180,9 @@ $(LCR): main.o \
action_vbox.o \
action_efi.o \
mail.o \
call.o \
callpbx.o \
callasterisk.o \
join.o \
joinpbx.o \
joinasterisk.o \
admin_server.o \
trace.o
$(LD) $(LIBDIR) \
@ -207,9 +207,9 @@ $(LCR): main.o \
action_vbox.o \
action_efi.o \
mail.o \
call.o \
callpbx.o \
callasterisk.o \
join.o \
joinpbx.o \
joinasterisk.o \
admin_server.o \
trace.o \
$(LIBS) -o $(LCR)

2
README
View File

@ -354,7 +354,9 @@ Changes in Version 1.0
- Asterisk channel driver integrated
- Multiplexing calls to multiple extensions
- Removed all VoIP stuff to make core fast and stable (Use Asterisk for VoIP.)
- Fixed a bug that caused some isdn connections to hang during disconnect
- Many bug fixes
- Many minor improvements
- New bugs of course...
- Rename of 'Call' instances to 'Join', because they join parties together.

View File

@ -71,12 +71,12 @@ char *numberrize_callerinfo(char *string, int ntype)
*/
void EndpointAppPBX::_action_init_call(int asterisk)
{
class Call *call;
class Join *join;
struct port_list *portlist = ea_endpoint->ep_portlist;
struct admin_list *admin;
/* a created call, this should never happen */
if (ea_endpoint->ep_call_id)
if (ea_endpoint->ep_join_id)
{
if (options.deb & DEBUG_EPOINT)
PERROR("EPOINT(%d): We already have a call instance, this should never happen!\n", ea_endpoint->ep_serial);
@ -102,13 +102,13 @@ void EndpointAppPBX::_action_init_call(int asterisk)
set_tone(portlist,"cause_22");
return;
}
call = new CallAsterisk(ea_endpoint->ep_serial);
join = new JoinAsterisk(ea_endpoint->ep_serial);
}
else
call = new CallPBX(ea_endpoint);
if (!call)
join = new JoinPBX(ea_endpoint);
if (!join)
FATAL("No memoy for Call instance.\n");
ea_endpoint->ep_call_id = call->c_serial;
ea_endpoint->ep_join_id = join->c_serial;
}
void EndpointAppPBX::action_init_call(void)
{
@ -137,7 +137,7 @@ void EndpointAppPBX::action_dialing_internal(void)
set_tone(portlist, "proceeding");
message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
message_put(message);
logmessage(message);
logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
new_state(EPOINT_STATE_IN_PROCEEDING);
/* create bearer/caller/dialinginfo */
@ -217,7 +217,7 @@ void EndpointAppPBX::action_dialing_internal(void)
trace_header("ACTION extension (calling)", DIRECTION_NONE);
add_trace("extension", NULL, dialinginfo.id);
end_trace();
message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_SETUP);
message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_SETUP);
memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
memcpy(&message->param.setup.redirinfo, &redirinfo, sizeof(struct redir_info));
memcpy(&message->param.setup.callerinfo, &callerinfo, sizeof(struct caller_info));
@ -342,7 +342,7 @@ void EndpointAppPBX::action_dialing_external(void)
{
trace_header("ACTION extern (calling denied)", DIRECTION_NONE);
end_trace();
release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, 0);
release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, 0);
set_tone(portlist, "cause_82");
denied:
message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
@ -359,7 +359,7 @@ void EndpointAppPBX::action_dialing_external(void)
{
trace_header("ACTION extern (national calls denied)", DIRECTION_NONE);
end_trace();
release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, 0);
release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, 0);
set_tone(portlist, "cause_83");
goto denied;
}
@ -373,7 +373,7 @@ void EndpointAppPBX::action_dialing_external(void)
{
trace_header("ACTION extern (international calls denied)", DIRECTION_NONE);
end_trace();
release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, 0);
release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, 0);
set_tone(portlist, "cause_84");
goto denied;
}
@ -385,7 +385,7 @@ void EndpointAppPBX::action_dialing_external(void)
if (dialinginfo.interfaces[0])
add_trace("interfaces", NULL, dialinginfo.interfaces);
end_trace();
message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_SETUP);
message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_SETUP);
memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
memcpy(&message->param.setup.redirinfo, &redirinfo, sizeof(struct redir_info));
memcpy(&message->param.setup.callerinfo, &callerinfo, sizeof(struct caller_info));
@ -457,7 +457,7 @@ void EndpointAppPBX::action_dialing_vbox_record(void)
set_tone(portlist, "proceeding");
message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
message_put(message);
logmessage(message);
logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
new_state(EPOINT_STATE_IN_PROCEEDING);
memset(&dialinginfo, 0, sizeof(dialinginfo));
@ -477,7 +477,7 @@ void EndpointAppPBX::action_dialing_vbox_record(void)
trace_header("ACTION vbox-record (calling)", DIRECTION_NONE);
add_trace("extension", NULL, "%s", dialinginfo.id);
end_trace();
message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_SETUP);
message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_SETUP);
memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
@ -491,13 +491,13 @@ void EndpointAppPBX::action_dialing_vbox_record(void)
*/
void EndpointAppPBX::action_init_partyline(void)
{
class Call *call;
class CallPBX *callpbx;
class Join *join;
class JoinPBX *joinpbx;
struct port_list *portlist = ea_endpoint->ep_portlist;
struct message *message;
struct route_param *rparam;
int partyline;
struct call_relation *relation;
struct join_relation *relation;
portlist = ea_endpoint->ep_portlist;
@ -522,30 +522,30 @@ void EndpointAppPBX::action_init_partyline(void)
}
partyline = rparam->integer_value;
/* don't create call if partyline exists */
call = call_first;
while(call)
/* don't create join if partyline exists */
join = join_first;
while(join)
{
if (call->c_type == CALL_TYPE_PBX)
if (join->c_type == JOIN_TYPE_PBX)
{
callpbx = (class CallPBX *)call;
if (callpbx->c_partyline == rparam->integer_value)
joinpbx = (class JoinPBX *)join;
if (joinpbx->c_partyline == rparam->integer_value)
break;
}
call = call->next;
join = join->next;
}
if (!call)
if (!join)
{
/* create call */
PDEBUG(DEBUG_EPOINT, "EPOINT(%d): Creating new call instance.\n", ea_endpoint->ep_serial);
if (!(call = new CallPBX(ea_endpoint)))
FATAL("No memory for Call object\n");
/* create join */
PDEBUG(DEBUG_EPOINT, "EPOINT(%d): Creating new join instance.\n", ea_endpoint->ep_serial);
if (!(join = new JoinPBX(ea_endpoint)))
FATAL("No memory for join object\n");
} else
{
//NOTE: callpbx must be set here
/* add relation to existing call */
if (!(relation=callpbx->add_relation()))
FATAL("No memory for Call relation\n");
//NOTE: joinpbx must be set here
/* add relation to existing join */
if (!(relation=joinpbx->add_relation()))
FATAL("No memory for join relation\n");
relation->type = RELATION_TYPE_SETUP;
relation->channel_state = CHANNEL_STATE_CONNECT;
relation->rx_state = NOTIFY_STATE_ACTIVE;
@ -553,19 +553,19 @@ void EndpointAppPBX::action_init_partyline(void)
relation->epoint_id = ea_endpoint->ep_serial;
}
ea_endpoint->ep_call_id = call->c_serial;
ea_endpoint->ep_join_id = join->c_serial;
set_tone(portlist, "proceeding");
message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
message_put(message);
logmessage(message);
logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
new_state(EPOINT_STATE_IN_PROCEEDING);
/* send setup to call */
/* send setup to join */
trace_header("ACTION partyline (calling)", DIRECTION_NONE);
add_trace("room", NULL, "%d", partyline);
end_trace();
message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_SETUP);
message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_SETUP);
message->param.setup.partyline = partyline;
memcpy(&message->param.setup.dialinginfo, &e_dialinginfo, sizeof(struct dialing_info));
memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
@ -683,7 +683,7 @@ void EndpointAppPBX::action_dialing_login(void)
SCPY(message->param.connectinfo.display, apply_callerid_display(message->param.connectinfo.id, message->param.connectinfo.itype, message->param.connectinfo.ntype, message->param.connectinfo.present, message->param.connectinfo.screen, message->param.connectinfo.extension, message->param.connectinfo.name));
message->param.connectinfo.ntype = e_ext.callerid_type;
message_put(message);
logmessage(message);
logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
/* set our caller id */
SCPY(e_callerinfo.id, e_ext.callerid);
@ -1047,7 +1047,7 @@ void EndpointAppPBX::_action_redial_reply(int in)
SPRINT(message->param.notifyinfo.display, "(%d) %s", e_select+1, (last[0])?last:"- empty -");
PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s sending display:%s\n", ea_endpoint->ep_serial, e_ext.number, message->param.notifyinfo.display);
message_put(message);
logmessage(message);
logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
}
/* process dialing redial
@ -1120,7 +1120,7 @@ void EndpointAppPBX::action_dialing_powerdial(void)
memset(&e_connectinfo, 0, sizeof(e_connectinfo));
message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
message_put(message);
logmessage(message);
logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
/* do dialing */
SCPY(e_dialinginfo.id, e_ext.last_out[0]);
@ -1321,7 +1321,7 @@ void EndpointAppPBX::action_dialing_test(void)
set_tone(portlist, "proceeding");
message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
message_put(message);
logmessage(message);
logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
break;
case '2':
@ -1332,7 +1332,7 @@ void EndpointAppPBX::action_dialing_test(void)
set_tone(portlist, "ringpbx");
message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
message_put(message);
logmessage(message);
logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
break;
case '3':
@ -1357,7 +1357,7 @@ void EndpointAppPBX::action_dialing_test(void)
/* 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.extension, message->param.connectinfo.name));
message_put(message);
logmessage(message);
logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
port = find_port_id(portlist->port_id);
if (port)
@ -1376,7 +1376,7 @@ void EndpointAppPBX::action_dialing_test(void)
memset(&e_connectinfo, 0, sizeof(e_connectinfo));
message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
message_put(message);
logmessage(message);
logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
set_tone(portlist, "test");
break;
@ -1390,7 +1390,7 @@ void EndpointAppPBX::action_dialing_test(void)
memset(&e_connectinfo, 0, sizeof(e_connectinfo));
message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
message_put(message);
logmessage(message);
logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
set_tone(portlist, "hold");
break;
@ -1412,7 +1412,7 @@ void EndpointAppPBX::action_dialing_test(void)
memset(&e_connectinfo, 0, sizeof(e_connectinfo));
message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
message_put(message);
logmessage(message);
logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
set_tone(portlist, causestr);
break;
@ -1459,7 +1459,7 @@ void EndpointAppPBX::action_dialing_test(void)
message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(message->param.connectinfo));
message_put(message);
logmessage(message);
logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
set_tone(portlist, "hold");
break;
}
@ -1752,7 +1752,7 @@ void EndpointAppPBX::action_dialing_calculator(void)
SPRINT(message->param.notifyinfo.display, ">%s", e_extdialing);
PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s displaying interpreted dialing '%s' internal values: %f %f\n", ea_endpoint->ep_serial, e_ext.number, e_extdialing, value1, value2);
message_put(message);
logmessage(message);
logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
}
@ -1906,7 +1906,7 @@ void EndpointAppPBX::action_dialing_disconnect(void)
message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
SCPY(message->param.notifyinfo.display, display);
message_put(message);
logmessage(message);
logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
}
e_action = NULL;
}
@ -1988,7 +1988,7 @@ nesting?:
SPRINT(message->param.notifyinfo.display, ">%s %s%s%s", numbering->prefix, numb_actions[numbering->action], (numbering->param[0])?" ":"", numbering->param);
PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s selected a new menu '%s' sending display:%s\n", ea_endpoint->ep_serial, e_ext.number, numb_actions[numbering->action], message->param.notifyinfo.display);
message_put(message);
logmessage(message);
logmessage(message->type, message->paramea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
#endif
}
@ -2112,7 +2112,7 @@ void EndpointAppPBX::action_init_pick(void)
if (extensions) if (extensions[0])
add_trace("extensions", NULL, "%s", extensions);
end_trace();
pick_call(extensions);
pick_join(extensions);
}
@ -2238,7 +2238,7 @@ void EndpointAppPBX::process_dialing(void)
release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
goto end;
}
release(RELEASE_CALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, 0);
release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, 0);
e_action = e_action->next;
if (!e_action)
{
@ -2287,7 +2287,7 @@ void EndpointAppPBX::process_dialing(void)
SCPY(message->param.notifyinfo.display,get_isdn_cause(LOCATION_PRIVATE_LOCAL, epoint->e_ext.display_cause, param->disconnectinfo.location, param->disconnectinfo.cause));
}
message_put(message);
logmessage(message);
logmessage(message->type, message->param, portlist->port_id, DIRECTION_OUT);
}
new_state(EPOINT_STATE_OUT_DISCONNECT);
set_tone(portlist,"cause_1c");
@ -2397,7 +2397,7 @@ void EndpointAppPBX::process_dialing(void)
memset(&e_connectinfo, 0, sizeof(e_connectinfo));
message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
message_put(message);
logmessage(message);
logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
} else
if ((rparam = routeparam(e_action, PARAM_ALERTING)))
{
@ -2405,7 +2405,7 @@ void EndpointAppPBX::process_dialing(void)
memset(&e_connectinfo, 0, sizeof(e_connectinfo));
message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
message_put(message);
logmessage(message);
logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
} else
if ((rparam = routeparam(e_action, PARAM_PROCEEDING)))
{
@ -2413,7 +2413,7 @@ void EndpointAppPBX::process_dialing(void)
memset(&e_connectinfo, 0, sizeof(e_connectinfo));
message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
message_put(message);
logmessage(message);
logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
}
if (action_defs[e_action->index].init_func)
@ -2468,7 +2468,7 @@ void EndpointAppPBX::process_dialing(void)
PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s displaying interpreted dialing '%s'\n", ea_endpoint->ep_serial, e_ext.number, message->param.notifyinfo.display);
message_put(message);
logmessage(message);
logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
}
end:

View File

@ -43,7 +43,7 @@ void EndpointAppPBX::action_init_efi(void)
message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
message->param.disconnectinfo.cause = CAUSE_FACILITYREJECTED;
message_put(message);
logmessage(message);
logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
new_state(EPOINT_STATE_OUT_DISCONNECT);
set_tone(portlist,"cause_22");
return;
@ -114,7 +114,7 @@ void EndpointAppPBX::efi_message_eof(void)
message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
message->param.disconnectinfo.cause = CAUSE_NORMAL;
message_put(message);
logmessage(message);
logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
new_state(EPOINT_STATE_OUT_DISCONNECT);
set_tone(portlist,"cause_10");
// set_tone_efi("ich_wiederhole");

View File

@ -102,7 +102,7 @@ void EndpointAppPBX::action_init_vbox_play(void)
e_dtmf = 1;
message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
message_put(message);
logmessage(message);
logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
/* initialize the vbox */
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) initializing answering vbox state\n", ea_endpoint->ep_serial);
@ -679,7 +679,7 @@ void EndpointAppPBX::vbox_handler(void)
SPRINT(message->param.notifyinfo.display, e_vbox_display, counter);
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) terminal %s pending display:%s\n", ea_endpoint->ep_serial, e_ext.number, message->param.notifyinfo.display);
message_put(message);
logmessage(message);
logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
}
}

18
admin.h
View File

@ -1,6 +1,6 @@
/*****************************************************************************\
** **
** PBX4Linux **
** Linux Call Router **
** **
**---------------------------------------------------------------------------**
** Copyright: Andreas Eversberg **
@ -29,7 +29,7 @@ enum { /* messages */
ADMIN_RESPONSE_S_INTERFACE,
ADMIN_RESPONSE_S_PORT,
ADMIN_RESPONSE_S_EPOINT,
ADMIN_RESPONSE_S_CALL,
ADMIN_RESPONSE_S_JOIN,
ADMIN_CALL_SETUP,
ADMIN_CALL_SETUP_ACK,
ADMIN_CALL_PROCEEDING,
@ -55,7 +55,7 @@ struct admin_response_state {
struct tm tm;
char logfile[128];
int interfaces;
int calls;
int joins;
int epoints;
int ports;
};
@ -76,16 +76,16 @@ struct admin_response_interface {
unsigned long port[256]; /* current port */
};
struct admin_response_call {
unsigned long serial; /* call serial number */
struct admin_response_join {
unsigned long serial; /* join serial number */
unsigned long partyline;
};
struct admin_response_epoint {
unsigned long serial;
unsigned long call; /* link to call */
// int call_notify; /* if relation notified on hold */
// int call_hold; /* if relation on hold */
unsigned long join; /* link to join */
// int join_notify; /* if relation notified on hold */
// int join_hold; /* if relation on hold */
int rx_state;
int tx_state;
int state;
@ -152,7 +152,7 @@ struct admin_message {
struct admin_response_interface i;
struct admin_response_port p;
struct admin_response_epoint e;
struct admin_response_call c;
struct admin_response_join j;
struct admin_call call;
struct admin_msg msg;
struct admin_trace_req trace_req;

View File

@ -1,6 +1,6 @@
/*****************************************************************************\
** **
** LCR **
** Linux Call Router **
** **
**---------------------------------------------------------------------------**
** Copyright: Andreas Eversberg **
@ -21,8 +21,8 @@
#include <sys/un.h>
#include <curses.h>
#include "macro.h"
#include "call.h"
#include "callpbx.h"
#include "join.h"
#include "joinpbx.h"
#include "extension.h"
#include "message.h"
#include "admin.h"
@ -73,7 +73,7 @@ char red = 1,
white = 7;
#define LOGLINES 128
char logline[LOGLINES][256];
char logline[LOGLINES][512];
unsigned long logcur = 0;
int logfh = -1;
char logfile[128];
@ -357,7 +357,7 @@ int debug_epoint(struct admin_message *msg, struct admin_message *m, int line, i
}
/* loop all related ports */
ltee = 0;
j = msg->u.s.interfaces+msg->u.s.calls+msg->u.s.epoints;
j = msg->u.s.interfaces+msg->u.s.joins+msg->u.s.epoints;
jj = j + msg->u.s.ports;
while(j < jj)
{
@ -388,39 +388,39 @@ int debug_epoint(struct admin_message *msg, struct admin_message *m, int line, i
return(line);
}
int debug_call(struct admin_message *msg, struct admin_message *m, int line, int i)
int debug_join(struct admin_message *msg, struct admin_message *m, int line, int i)
{
unsigned long call = m[i].u.c.serial;
unsigned long join = m[i].u.j.serial;
char buffer[256];
int j, jj;
color(white);
SPRINT(buffer,"CALL(%d)", call);
SPRINT(buffer,"JOIN(%d)", join);
addstr(buffer);
if (m[i].u.c.partyline)
if (m[i].u.j.partyline)
{
color(cyan);
addstr(" partyline=");
color(white);
SPRINT(buffer, "%d\n", m[i].u.c.partyline);
SPRINT(buffer, "%d\n", m[i].u.j.partyline);
addstr(buffer);
}
/* find number of epoints */
j = msg->u.s.interfaces+msg->u.s.calls;
j = msg->u.s.interfaces+msg->u.s.joins;
jj = j + msg->u.s.epoints;
i = 0;
while(j < jj)
{
if (m[j].u.e.call == call)
if (m[j].u.e.join == join)
i++;
j++;
}
/* loop all related endpoints */
j = msg->u.s.interfaces+msg->u.s.calls;
j = msg->u.s.interfaces+msg->u.s.joins;
jj = j + msg->u.s.epoints;
while(j < jj)
{
if (m[j].u.e.call == call)
if (m[j].u.e.join == join)
{
i--;
move(++line>1?line:1, 1);
@ -443,7 +443,7 @@ char *admin_state(int sock)
{
struct admin_message msg,
*m;
char buffer[256],
char buffer[512],
*p;
int line, offset = 0;
int i, ii, j, jj, k;
@ -483,7 +483,7 @@ char *admin_state(int sock)
cleanup_curses();
return("Response not valid. Expecting state response.");
}
num = msg.u.s.interfaces + msg.u.s.calls + msg.u.s.epoints + msg.u.s.ports;
num = msg.u.s.interfaces + msg.u.s.joins + msg.u.s.epoints + msg.u.s.ports;
m = (struct admin_message *)MALLOC(num*sizeof(struct admin_message));
off=0;
if (num)
@ -520,9 +520,9 @@ char *admin_state(int sock)
j++;
}
i = 0;
while(i < msg.u.s.calls)
while(i < msg.u.s.joins)
{
if (m[j].message != ADMIN_RESPONSE_S_CALL)
if (m[j].message != ADMIN_RESPONSE_S_JOIN)
{
FREE(m, 0);
cleanup_curses();
@ -705,7 +705,7 @@ char *admin_state(int sock)
if (m[i].u.i.port[j])
{
/* search for port */
l = msg.u.s.interfaces+msg.u.s.calls+msg.u.s.epoints;
l = msg.u.s.interfaces+msg.u.s.joins+msg.u.s.epoints;
ll = l+msg.u.s.ports;
while(l < ll)
{
@ -769,12 +769,12 @@ char *admin_state(int sock)
if (show_calls == 1)
{
anything = 0;
i = msg.u.s.interfaces+msg.u.s.calls;
i = msg.u.s.interfaces+msg.u.s.joins;
ii = i+msg.u.s.epoints;
while(i < ii)
{
/* for each endpoint... */
if (!m[i].u.e.call)
if (!m[i].u.e.join)
{
move(++line>1?line:1, 0);
color(white);
@ -809,20 +809,20 @@ char *admin_state(int sock)
anything = 1;
}
j = msg.u.s.interfaces;
jj = j+msg.u.s.calls;
jj = j+msg.u.s.joins;
while(j < jj)
{
/* for each call... */
move(++line>1?line:1, 0);
color(white);
SPRINT(buffer, "(%d):", m[j].u.c.serial);
SPRINT(buffer, "(%d):", m[j].u.j.serial);
addstr(buffer);
i = msg.u.s.interfaces+msg.u.s.calls;
i = msg.u.s.interfaces+msg.u.s.joins;
ii = i+msg.u.s.epoints;
while(i < ii)
{
/* for each endpoint... */
if (m[i].u.e.call == m[j].u.c.serial)
if (m[i].u.e.join == m[j].u.j.serial)
{
color(white);
SPRINT(buffer, " (%d)", m[i].u.e.serial);
@ -859,7 +859,7 @@ char *admin_state(int sock)
{
/* show all ports with no epoint */
anything = 0;
i = msg.u.s.interfaces+msg.u.s.calls+msg.u.s.epoints;
i = msg.u.s.interfaces+msg.u.s.joins+msg.u.s.epoints;
ii = i+msg.u.s.ports;
while(i < ii)
{
@ -879,11 +879,11 @@ char *admin_state(int sock)
/* show all epoints with no call */
anything = 0;
i = msg.u.s.interfaces+msg.u.s.calls;
i = msg.u.s.interfaces+msg.u.s.joins;
ii = i+msg.u.s.epoints;
while(i < ii)
{
if (!m[i].u.e.call)
if (!m[i].u.e.join)
{
move(++line>1?line:1, 4);
if (line+2 >= LINES) goto end;
@ -897,15 +897,15 @@ char *admin_state(int sock)
line++;
if (line+2 >= LINES) goto end;
/* show all calls */
/* show all joins */
anything = 0;
i = msg.u.s.interfaces;
ii = i+msg.u.s.calls;
ii = i+msg.u.s.joins;
while(i < ii)
{
move(++line>1?line:1, 0);
if (line+2 >= LINES) goto end;
line = debug_call(&msg, m, line, i);
line = debug_join(&msg, m, line, i);
if (line+2 >= LINES) goto end;
i++;
anything = 1;
@ -934,7 +934,7 @@ char *admin_state(int sock)
{
move(line++>1?line-1:1, 0);
SCPY(buffer, logline[l % LOGLINES]);
if (COLS < (int)sizeof(buffer))
if (COLS < (int)strlen(buffer))
buffer[COLS] = '\0';
addstr(buffer);
l++;

View File

@ -1,11 +1,11 @@
/*****************************************************************************\
** **
** PBX4Linux **
** Linux Call Router **
** **
**---------------------------------------------------------------------------**
** Copyright: Andreas Eversberg **
** **
** Socket link **
** Socket link server **
** **
\*****************************************************************************/
@ -93,24 +93,24 @@ void free_connection(struct admin_list *admin)
struct admin_queue *response;
void *temp;
union parameter param;
class Call *call, *callnext;
class Join *join, *joinnext;
/* free asterisk joins */
if (admin->asterisk)
{
call = call_first;
while(call)
join = join_first;
while(join)
{
callnext = call->next;
if (call->c_type == CALL_TYPE_ASTERISK)
joinnext = join->next;
if (join->c_type == JOIN_TYPE_ASTERISK)
{
memset(&param, 0, sizeof(param));
param.disconnectinfo.cause = CAUSE_OUTOFORDER;
param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
((class CallAsterisk *)call)->message_asterisk(0, MESSAGE_RELEASE, &param);
/* call is now destroyed, so we go to next call */
((class JoinAsterisk *)join)->message_asterisk(0, MESSAGE_RELEASE, &param);
/* join is now destroyed, so we go to next join */
}
call = callnext;
join = joinnext;
}
}
@ -595,7 +595,7 @@ void admin_call_response(int adminid, int message, char *connected, int cause, i
*/
int admin_message_to_join(struct admin_msg *msg)
{
class Call *call;
class Join *join;
struct admin_list *admin;
/* dummy callref means: asterisk is here */
@ -618,17 +618,17 @@ int admin_message_to_join(struct admin_msg *msg)
admin->asterisk = 1;
}
/* find call instance */
call = call_first;
while(call)
/* find join instance */
join = join_first;
while(join)
{
if (call->c_serial == msg->ref)
if (join->c_serial == msg->ref)
break;
call = call->next;
join = join->next;
}
/* create call instance if not existing */
if (!call)
/* create join instance if not existing */
if (!join)
{
if (msg->ref < 2000000000)
{
@ -636,16 +636,16 @@ int admin_message_to_join(struct admin_msg *msg)
return(-1);
}
/* create new call instance */
call = new CallAsterisk(0); // must have no serial, because no endpoint is connected
if (!call)
FATAL("No memory for Asterisk Call instance\n");
/* create new join instance */
join = new JoinAsterisk(0); // must have no serial, because no endpoint is connected
if (!join)
FATAL("No memory for Asterisk join instance\n");
}
/* send message */
if (call->c_type != CALL_TYPE_ASTERISK)
FATAL("Call instance %d must be of type Call Asterisk\n", call->c_serial);
((class CallAsterisk *)call)->message_asterisk(msg->ref, msg->type, &msg->param);
if (join->c_type != JOIN_TYPE_ASTERISK)
FATAL("join instance %d must be of type join Asterisk\n", join->c_serial);
((class JoinAsterisk *)join)->message_asterisk(msg->ref, msg->type, &msg->param);
return(0);
}
@ -708,7 +708,7 @@ int admin_state(struct admin_queue **responsep)
class Port *port;
class EndpointAppPBX *apppbx;
class Call *call;
class Join *join;
class Pdss1 *pdss1;
struct interface *interface;
struct interface_port *ifport;
@ -744,15 +744,15 @@ int admin_state(struct admin_queue **responsep)
interface = interface->next;
}
response->am[0].u.s.interfaces = i;
/* call count */
call = call_first;
/* join count */
join = join_first;
i = 0;
while(call)
while(join)
{
i++;
call = call->next;
join = join->next;
}
response->am[0].u.s.calls = i;
response->am[0].u.s.joins = i;
/* apppbx count */
apppbx = apppbx_first;
i = 0;
@ -776,7 +776,7 @@ int admin_state(struct admin_queue **responsep)
responsep = &response->next;
/* create response for all interfaces */
num = (response->am[0].u.s.interfaces)+(response->am[0].u.s.calls)+(response->am[0].u.s.epoints)+(response->am[0].u.s.ports);
num = (response->am[0].u.s.interfaces)+(response->am[0].u.s.joins)+(response->am[0].u.s.epoints)+(response->am[0].u.s.ports);
if (num == 0)
return(0);
response = (struct admin_queue *)MALLOC(sizeof(admin_queue)+(num*sizeof(admin_message)));
@ -837,19 +837,19 @@ int admin_state(struct admin_queue **responsep)
interface = interface->next;
}
/* create response for all calls */
call = call_first;
while(call)
/* create response for all joins */
join = join_first;
while(join)
{
/* message */
response->am[num].message = ADMIN_RESPONSE_S_CALL;
response->am[num].message = ADMIN_RESPONSE_S_JOIN;
/* serial */
response->am[num].u.c.serial = call->c_serial;
response->am[num].u.j.serial = join->c_serial;
/* partyline */
if (call->c_type == CALL_TYPE_PBX)
response->am[num].u.c.partyline = ((class CallPBX *)call)->c_partyline;
if (join->c_type == JOIN_TYPE_PBX)
response->am[num].u.j.partyline = ((class JoinPBX *)join)->c_partyline;
/* */
call = call->next;
join = join->next;
num++;
}
@ -861,8 +861,8 @@ int admin_state(struct admin_queue **responsep)
response->am[num].message = ADMIN_RESPONSE_S_EPOINT;
/* serial */
response->am[num].u.e.serial = apppbx->ea_endpoint->ep_serial;
/* call */
response->am[num].u.e.call = apppbx->ea_endpoint->ep_call_id;
/* join */
response->am[num].u.e.join = apppbx->ea_endpoint->ep_join_id;
/* rx notification */
response->am[num].u.e.rx_state = apppbx->e_rx_state;
/* tx notification */

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/*****************************************************************************\
** **
** PBX4Linux **
** Linux Call Router **
** **
**---------------------------------------------------------------------------**
** Copyright: Andreas Eversberg **
@ -12,9 +12,9 @@
enum { /* release actions: see epoint.release */
RELEASE_NONE,
RELEASE_CALL, /* call, hold */
RELEASE_PORT_CALLONLY, /* call, port */
RELEASE_ALL, /* call, hold, port */
RELEASE_JOIN, /* join, hold */
RELEASE_PORT_JOINONLY, /* join, port */
RELEASE_ALL, /* join, hold, port */
};
enum { /* states as viewed from io port (state of calls are always connected) */
@ -92,8 +92,8 @@ class EndpointAppPBX : public EndpointApp
// int e_knocking; /* true, if knocking */
// double e_knocktime; /* next time to knock */
// char e_call_tone[64], e_hold_tone[64]; /* current tone */
int e_call_pattern/*, e_hold_pattern*/; /* pattern available */
// char e_join_tone[64], e_hold_tone[64]; /* current tone */
int e_join_pattern/*, e_hold_pattern*/; /* pattern available */
/* action */
char e_dialing_queue[32]; /* holds dialing during setup state */
@ -111,9 +111,9 @@ class EndpointAppPBX : public EndpointApp
int e_multipoint_cause; /* cause value of disconnected multiport calls (highest priority) */
int e_multipoint_location; /* location of cause with highest priority */
/* call relation */
int e_call_cause;
int e_call_location;
/* join relation */
int e_join_cause;
int e_join_location;
/* callback */
char e_cbdialing[256]; /* dialing information after callback */
@ -205,22 +205,22 @@ class EndpointAppPBX : public EndpointApp
void port_facility(struct port_list *portlist, int message_type, union parameter *param);
void port_suspend(struct port_list *portlist, int message_type, union parameter *param);
void port_resume(struct port_list *portlist, int message_type, union parameter *param);
void ea_message_call(unsigned long call_id, int message, union parameter *param);
void call_crypt(struct port_list *portlist, int message_type, union parameter *param);
void call_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param);
void call_setup(struct port_list *portlist, int message_type, union parameter *param);
void call_information(struct port_list *portlist, int message_type, union parameter *param);
void call_overlap(struct port_list *portlist, int message_type, union parameter *param);
void call_proceeding(struct port_list *portlist, int message_type, union parameter *param);
void call_alerting(struct port_list *portlist, int message_type, union parameter *param);
void call_connect(struct port_list *portlist, int message_type, union parameter *param);
void call_disconnect_release(struct port_list *portlist, int message_type, union parameter *param);
void call_notify(struct port_list *portlist, int message_type, union parameter *param);
void call_facility(struct port_list *portlist, int message_type, union parameter *param);
void ea_message_join(unsigned long 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_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);
void join_proceeding(struct port_list *portlist, int message_type, union parameter *param);
void join_alerting(struct port_list *portlist, int message_type, union parameter *param);
void join_connect(struct port_list *portlist, int message_type, union parameter *param);
void join_disconnect_release(struct port_list *portlist, int message_type, union parameter *param);
void join_notify(struct port_list *portlist, int message_type, union parameter *param);
void join_facility(struct port_list *portlist, int message_type, union parameter *param);
/* epoint */
void new_state(int state);
void release(int release, int calllocation, int callcause, int portlocation, int portcause);
void release(int release, int joinlocation, int joincause, int portlocation, int portcause);
void notify_active(void);
void keypad_function(char digit);
void set_tone(struct port_list *portlist, char *tone);
@ -297,8 +297,8 @@ class EndpointAppPBX : public EndpointApp
void process_hangup(int cause, int location);
/* facility function */
void pick_call(char *extension);
void join_call(void);
void pick_join(char *extension);
void join_join(void);
void encrypt_shared(void);
void encrypt_keyex(void);
void encrypt_off(void);
@ -345,7 +345,7 @@ class EndpointAppPBX : public EndpointApp
void cryptman_timeout(int secs);
void message_disconnect_port(struct port_list *portlist, int cause, int location, char *display);
void logmessage(struct message *messsage);
void logmessage(int message_type, union parameter *param, unsigned long port_id, int dir);
void trace_header(char *name, int direction);
void screen(int out, char *id, int idsize, int *type, int *present, struct interface *interface);
};

View File

@ -1524,7 +1524,7 @@ void EndpointAppPBX::cryptman_msg2user(int msg, char *text)
{
struct message *message;
/* send message */
message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CRYPT);
message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CRYPT);
message->param.crypt.type = msg;
if (!text)
text = "";
@ -1803,7 +1803,7 @@ void EndpointAppPBX::encrypt_shared(void)
if (e_crypt != CRYPT_OFF)
{
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) encryption in progress, so we request the current message.\n", ea_endpoint->ep_serial);
message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CRYPT);
message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CRYPT);
message->param.crypt.type = CU_INFO_REQ;
message_put(message);
return;
@ -1885,7 +1885,7 @@ void EndpointAppPBX::encrypt_shared(void)
// SPRINT(e_crypt_display, "Shared Key");
e_crypt = CRYPT_SWAIT;
/* sending activation */
message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CRYPT);
message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CRYPT);
message->param.crypt.type = CU_ACTS_REQ;
message->param.crypt.len = key_len;
memcpy(message->param.crypt.data, key, key_len);
@ -1905,7 +1905,7 @@ void EndpointAppPBX::encrypt_keyex(void)
if (e_crypt != CRYPT_OFF)
{
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) encryption in progress, so we request the current message.\n", ea_endpoint->ep_serial);
message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CRYPT);
message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CRYPT);
message->param.crypt.type = CU_INFO_REQ;
message_put(message);
return;
@ -1937,7 +1937,7 @@ void EndpointAppPBX::encrypt_keyex(void)
message_put(message);
e_crypt = CRYPT_KWAIT;
/* sending activation */
message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CRYPT);
message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CRYPT);
message->param.crypt.type = CU_ACTK_REQ;
message_put(message);
#endif /* CRYPTO */
@ -1975,7 +1975,7 @@ void EndpointAppPBX::encrypt_off(void)
message_put(message);
e_crypt = CRYPT_RELEASE;
/* sending activation */
message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_call_id, EPOINT_TO_CALL, MESSAGE_CRYPT);
message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CRYPT);
message->param.crypt.type = CU_DACT_REQ;
message_put(message);
}

View File

@ -1121,7 +1121,7 @@ void Pdss1::disconnect_ind(unsigned long prim, unsigned long dinfo, void *data)
cause = 16;
/* release if we are remote sends us no tones */
if (p_m_mISDNport->earlyb)
if (!p_m_mISDNport->earlyb)
{
RELEASE_t *release;
msg_t *dmsg;
@ -1242,7 +1242,7 @@ void Pdss1::release_ind(unsigned long prim, unsigned long dinfo, void *data)
p_m_delete = 1;
}
/* CC_RELEASE_COMPLETE INDICATION */
/* CC_RELEASE_COMPLETE INDICATION (a reject) */
void Pdss1::release_complete_ind(unsigned long prim, unsigned long dinfo, void *data)
{
int headerlen = (p_m_d_ntmode)?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
@ -1867,9 +1867,10 @@ void Pdss1::message_isdn(unsigned long prim, unsigned long dinfo, void *data)
}
p_m_d_l3id = 0;
p_m_delete = 1;
#warning remove me
PDEBUG(DEBUG_LOG, "JOLLY release cr %d\n", p_serial);
/* sending release to endpoint in case we still have an endpoint
* NOTE: this only happens if the stack releases due to layer1
* or layer2 breakdown. otherwhise a release is received first.
* this is because we don't get any response if a release_complete is received (or a release in release state)
*/
while(p_epointlist)
{
@ -1968,12 +1969,17 @@ int Pdss1::handler(void)
{
int ret;
if (p_m_delete && p_m_d_l3id==0)
printf("ping! %d", p_serial);
if ((ret = PmISDN::handler()))
return(ret);
/* handle destruction */
if (p_m_delete && p_m_d_l3id==0)
{
#warning remove
PDEBUG(DEBUG_LOG, "JOLLY destroy object %d\n", p_serial);
delete this;
return(-1);
}
@ -2665,8 +2671,8 @@ void Pdss1::message_disconnect(unsigned long epoint_id, int message_id, union pa
char *p = NULL;
/* we reject during incoming setup when we have no tones. also if we are in outgoing setup state */
if ((p_state==PORT_STATE_IN_SETUP && !p_m_mISDNport->tones)
|| p_state==PORT_STATE_OUT_SETUP)
// if ((p_state==PORT_STATE_IN_SETUP && !p_m_mISDNport->tones)
if (/* ||*/ p_state==PORT_STATE_OUT_SETUP)
{
/* sending release to endpoint */
while(p_epointlist)
@ -2691,7 +2697,7 @@ void Pdss1::message_disconnect(unsigned long epoint_id, int message_id, union pa
return;
}
/* NT-MODE in setup state we must send PROCEEDING first */
/* workarround: NT-MODE in setup state we must send PROCEEDING first to make it work */
if (p_state==PORT_STATE_IN_SETUP)
{
CALL_PROCEEDING_t *proceeding;
@ -2745,9 +2751,11 @@ void Pdss1::message_release(unsigned long epoint_id, int message_id, union param
class Endpoint *epoint;
char *p = NULL;
/* if we have incoming disconnected, we may release */
if (p_state==PORT_STATE_IN_DISCONNECT
|| p_state==PORT_STATE_OUT_DISCONNECT)
/*
* we may only release during incomming disconnect state.
* this means that the endpoint doesnt require audio anymore
*/
if (p_state == PORT_STATE_IN_DISCONNECT)
{
/* sending release */
dmsg = create_l3msg(CC_RELEASE | REQUEST, MT_RELEASE, p_m_d_l3id, sizeof(RELEASE_t), p_m_d_ntmode);
@ -2758,16 +2766,24 @@ void Pdss1::message_release(unsigned long epoint_id, int message_id, union param
end_trace();
msg_queue_tail(&p_m_mISDNport->downqueue, dmsg);
new_state(PORT_STATE_RELEASE);
/* remove epoint */
free_epointid(epoint_id);
// wait for callref to be released
return;
}
/* if we are on outgoing/incoming call setup, we may release complete */
if (p_state==PORT_STATE_OUT_SETUP
|| p_state==PORT_STATE_IN_SETUP
// NOTE: a bug in mISDNuser (see disconnect_req_out !!!)
|| p_state==PORT_STATE_OUT_PROCEEDING)
/*
* if we are on incoming call setup, we may reject by sending a release_complete
* also on outgoing call setup, we send a release complete, BUT this is not conform. (i don't know any other way)
*/
if (p_state==PORT_STATE_IN_SETUP
|| p_state==PORT_STATE_OUT_SETUP)
// // NOTE: a bug in mISDNuser (see disconnect_req_out !!!)
// || p_state==PORT_STATE_OUT_DISCO)
{
/* sending release */
#warning remove me
PDEBUG(DEBUG_LOG, "JOLLY sending release complete %d\n", p_serial);
/* sending release complete */
dmsg = create_l3msg(CC_RELEASE_COMPLETE | REQUEST, MT_RELEASE_COMPLETE, p_m_d_l3id, sizeof(RELEASE_COMPLETE_t), p_m_d_ntmode);
release_complete = (RELEASE_COMPLETE_t *)(dmsg->data + headerlen);
l1l2l3_trace_header(p_m_mISDNport, this, CC_RELEASE | REQUEST, DIRECTION_OUT);
@ -2776,9 +2792,10 @@ void Pdss1::message_release(unsigned long epoint_id, int message_id, union param
end_trace();
msg_queue_tail(&p_m_mISDNport->downqueue, dmsg);
new_state(PORT_STATE_RELEASE);
/* remove epoint */
free_epointid(epoint_id);
#if 0
/* remove process */
l1l2l3_trace_header(p_m_mISDNport, this, CC_RELEASE_CR | REQUEST, DIRECTION_OUT);
add_trace("callref", NULL, "0x%x", p_m_d_l3id);
end_trace();
@ -2789,9 +2806,13 @@ void Pdss1::message_release(unsigned long epoint_id, int message_id, union param
}
p_m_d_l3id = 0;
p_m_delete = 1;
#endif
// wait for callref to be released
return;
}
#if 0
wirklich erst proceeding?:
/* NT-MODE in setup state we must send PROCEEDING first */
if (p_m_d_ntmode && p_state==PORT_STATE_IN_SETUP)
{
@ -2811,6 +2832,7 @@ void Pdss1::message_release(unsigned long epoint_id, int message_id, union param
end_trace();
msg_queue_tail(&p_m_mISDNport->downqueue, dmsg);
}
#endif
/* sending disconnect */
dmsg = create_l3msg(CC_DISCONNECT | REQUEST, MT_DISCONNECT, p_m_d_l3id, sizeof(DISCONNECT_t), p_m_d_ntmode);
@ -2832,9 +2854,12 @@ void Pdss1::message_release(unsigned long epoint_id, int message_id, union param
enc_ie_display(&disconnect->DISPLAY, dmsg, (unsigned char *)p);
end_trace();
msg_queue_tail(&p_m_mISDNport->downqueue, dmsg);
new_state(PORT_STATE_RELEASE);
new_state(PORT_STATE_OUT_DISCONNECT);
/* remove epoint */
free_epointid(epoint_id);
// p_m_delete = 1;
// wait for release and callref to be released
#warning remove me
PDEBUG(DEBUG_LOG, "JOLLY sending disconnect %d\n", p_serial);
}

View File

@ -1,11 +1,11 @@
/*****************************************************************************\
** **
** PBX4Linux **
** Linux Call Router **
** **
**---------------------------------------------------------------------------**
** Copyright: Andreas Eversberg **
** **
** The Endpoint is the link between the call and the port. **
** The Endpoint is the link between the join and the port. **
** **
\*****************************************************************************/
@ -37,16 +37,16 @@ class Endpoint *find_epoint_id(unsigned long epoint_id)
/*
* endpoint constructor (link with either port or call id)
* endpoint constructor (link with either port or join id)
*/
Endpoint::Endpoint(unsigned long port_id, unsigned long call_id, unsigned long use_epoint_id)
Endpoint::Endpoint(unsigned long port_id, unsigned long join_id, unsigned long use_epoint_id)
{
class Port *port;
class Endpoint **epointpointer;
int earlyb = 0;
/* epoint structure */
PDEBUG(DEBUG_EPOINT, "EPOINT(%d): Allocating enpoint %d and connecting it with:%s%s\n", epoint_serial, epoint_serial, (port_id)?" ioport":"", (call_id)?" call":"");
PDEBUG(DEBUG_EPOINT, "EPOINT(%d): Allocating enpoint %d and connecting it with:%s%s\n", epoint_serial, epoint_serial, (port_id)?" ioport":"", (join_id)?" join":"");
ep_portlist = NULL;
ep_app = NULL;
@ -65,7 +65,7 @@ Endpoint::Endpoint(unsigned long port_id, unsigned long call_id, unsigned long u
else
ep_serial = epoint_serial++;
/* link to call or port */
/* link to join or port */
if (port_id)
{
port = find_port_id(port_id);
@ -77,7 +77,7 @@ Endpoint::Endpoint(unsigned long port_id, unsigned long call_id, unsigned long u
FATAL("No memory for portlist.\n");
}
}
ep_call_id = call_id;
ep_join_id = join_id;
ep_park = 0;
ep_park_len = 0;
@ -101,9 +101,9 @@ Endpoint::~Endpoint(void)
delete ep_app;
/* free relations */
if (ep_call_id)
if (ep_join_id)
{
PERROR("warning: still relation to call.\n");
PERROR("warning: still relation to join.\n");
}
/* free portlist */
@ -158,7 +158,7 @@ struct port_list *Endpoint::portlist_new(unsigned long port_id, int port_type, i
portlistpointer = &((*portlistpointer)->next);
*portlistpointer = portlist;
/* link to call or port */
/* link to join or port */
portlist->port_id = port_id;
portlist->port_type = port_type;
portlist->early_b = earlyb;

View File

@ -1,6 +1,6 @@
/*****************************************************************************\
** **
** PBX4Linux **
** Linux Call Router **
** **
**---------------------------------------------------------------------------**
** Copyright: Andreas Eversberg **
@ -22,7 +22,7 @@ struct port_list {
class Endpoint
{
public:
Endpoint(unsigned long port_id, unsigned long call_id, unsigned long use_epoint_id);
Endpoint(unsigned long port_id, unsigned long join_id, unsigned long use_epoint_id);
~Endpoint();
class Endpoint *next; /* next in list */
unsigned long ep_serial; /* a unique serial to identify */
@ -36,8 +36,8 @@ class Endpoint
struct port_list *portlist_new(unsigned long port_id, int port_type, int earlyb);
void free_portlist(struct port_list *portlist);
/* call relation */
unsigned long ep_call_id; /* link to call */
/* join relation */
unsigned long ep_join_id; /* link to join */
/* if still used by threads */
int ep_use;

View File

@ -1,6 +1,6 @@
/*****************************************************************************\
** **
** PBX4Linux **
** Linux Call Router **
** **
**---------------------------------------------------------------------------**
** Copyright: Andreas Eversberg **
@ -42,7 +42,7 @@ void EndpointApp::ea_message_port(unsigned long port_id, int message_type, union
PDEBUG(DEBUG_EPOINT, "%s: Spare function.\n", __FUNCTION__);
}
void EndpointApp::ea_message_call(unsigned long port_id, int message_type, union parameter *param)
void EndpointApp::ea_message_join(unsigned long join_id, int message_type, union parameter *param)
{
PDEBUG(DEBUG_EPOINT, "%s: Spare function.\n", __FUNCTION__);
}

View File

@ -1,6 +1,6 @@
/*****************************************************************************\
** **
** PBX4Linux **
** Linux Call Router **
** **
**---------------------------------------------------------------------------**
** Copyright: Andreas Eversberg **
@ -20,6 +20,6 @@ class EndpointApp
class Endpoint *ea_endpoint;
virtual int handler(void);
virtual void ea_message_port(unsigned long port_id, int message, union parameter *param);
virtual void ea_message_call(unsigned long call_id, int message, union parameter *param);
virtual void ea_message_join(unsigned long join_id, int message, union parameter *param);
};

343
h323.cpp
View File

@ -1,343 +0,0 @@
/*****************************************************************************\
** **
** PBX4Linux **
** **
**---------------------------------------------------------------------------**
** Copyright: Andreas Eversberg **
** **
** h323 port **
** **
\*****************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <poll.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "main.h"
/*
* initialize h323 port
*/
H323Port::H323Port(int type, char *portname, struct port_settings *settings) : Port(type, portname, settings)
{
p_h323_channel_in = p_h323_channel_out = NULL;
p_h323_connect = NULL;
/* configure device */
switch (type)
{
case PORT_TYPE_H323_IN:
break;
case PORT_TYPE_H323_OUT:
SPRINT(p_name, "H323_outgoing_port_#%lu", p_serial);
break;
}
if (options.law == 'u')
{
}
}
/*
* destructor
*/
H323Port::~H323Port()
{
}
/*
* endpoint sends messages to the interface
*/
int H323Port::message_epoint(unsigned long epoint_id, int message_id, union parameter *param)
{
H323Connection *connection;
H323Connection::CallEndReason h323_cause;
char name[sizeof(p_name)];
if (Port::message_epoint(epoint_id, message_id, param))
return(1);
switch(message_id)
{
case MESSAGE_mISDNSIGNAL: /* isdn command */
PDEBUG(DEBUG_H323, "H323Port(%s) mISDN signal not supported.\n", p_name);
break;
case MESSAGE_INFORMATION: /* additional digits from endpoint */
PDEBUG(DEBUG_H323, "H323Port(%s) h323 port with (caller id %s) received more digit information: '%s'\n", p_name, p_callerinfo.id, param->information.number);
/* queue to be done */
if (p_state != PORT_STATE_OUT_OVERLAP)
{
PERROR("H323Port(%s) additinal digits are only possible in outgoing overlap state.\n", p_name);
break;
}
if (strlen(param->information.number)>30)
{
PERROR("H323Port(%s) information string too long.\n", p_name);
break;
}
SCAT((char *)p_dialinginfo.number, param->information.number);
break;
case MESSAGE_PROCEEDING: /* call of endpoint is proceeding */
PDEBUG(DEBUG_H323, "H323Port(%s) h323 port with (caller id %s) received proceeding\n", p_name, p_callerinfo.id);
if (p_state != PORT_STATE_IN_OVERLAP)
{
PERROR("H323Port(%s) proceeding command only possible in setup state.\n", p_name);
break;
}
p_state = PORT_STATE_IN_PROCEEDING;
break;
case MESSAGE_ALERTING: /* call of endpoint is ringing */
PDEBUG(DEBUG_H323, "H323Port(%s) h323 port with (caller id %s) received alerting\n", p_name, p_callerinfo.id);
if (p_state != PORT_STATE_IN_OVERLAP
&& p_state != PORT_STATE_IN_PROCEEDING)
{
PERROR("H323Port(%s) alerting command only possible in setup or proceeding state.\n", p_name);
break;
}
p_state = PORT_STATE_IN_ALERTING;
UCPY(name, p_name);
mutex_h323.Signal();
connection = h323_ep->FindConnectionWithLock(name);
if (connection)
{
if (options.h323_ringconnect && !p_callerinfo.intern[0])
{
connection->AnsweringCall(H323Connection::AnswerCallNow);
p_state = PORT_STATE_CONNECT;
} else
connection->AnsweringCall(H323Connection::AnswerCallPending);
connection->Unlock();
}
mutex_h323.Wait();
break;
case MESSAGE_CONNECT: /* call of endpoint is connected */
PDEBUG(DEBUG_H323, "H323Port(%s) h323 port with (caller id %s) received connect\n", p_name, p_callerinfo.id);
if (p_state != PORT_STATE_IN_OVERLAP
&& p_state != PORT_STATE_IN_PROCEEDING
&& p_state != PORT_STATE_IN_ALERTING)
{
PDEBUG(DEBUG_H323, "H323Port(%s) connect command only possible in setup, proceeding or alerting state.\n", p_name);
break;
}
new_state(PORT_STATE_CONNECT);
/* copy connected information */
memcpy(&p_connectinfo, &param->connectinfo, sizeof(p_connectinfo));
p_connectinfo.itype = INFO_ITYPE_H323;
UCPY(name, p_name);
mutex_h323.Signal();
connection = h323_ep->FindConnectionWithLock(name);
if (connection)
{
int type, present, screen;
PString connect_number;
/* modify connectinfo (COLP) */
if (p_connectinfo.present!=INFO_PRESENT_NULL)
{
connect_number = p_connectinfo.id;
switch(p_connectinfo.ntype)
{
case INFO_NTYPE_SUBSCRIBER:
type = Q931::SubscriberType;
break;
case INFO_NTYPE_NATIONAL:
type = Q931::NationalType;
break;
case INFO_NTYPE_INTERNATIONAL:
type = Q931::InternationalType;
break;
default: /* INFO_TYPE_UNKNOWN */
type = Q931::UnknownType;
}
switch(p_connectinfo.present)
{
case INFO_PRESENT_RESTRICTED:
present = 1;
break;
case INFO_PRESENT_NOTAVAIL:
present = 2;
break;
default: /* INFO_PRESENT_ALLOWED */
present = 0;
}
switch(p_connectinfo.screen)
{
case INFO_SCREEN_USER:
screen = 0;
break;
default: /* INFO_SCREEN_NETWORK */
screen = 3;
}
#if 0
if (p_h323_connect)
{
//PDEBUG(DEBUG_H323, "DDDEBUG: number %s, type=%d, present %d, screen %d\n", p_connectinfo.id, type, present, screen);
((Q931 *)p_h323_connect)->SetConnectedNumber(connect_number, Q931::ISDNPlan, type, present, screen);
}
else
PERROR("missing p_h323_connect\n");
#endif
}
connection->AnsweringCall(H323Connection::AnswerCallNow);
connection->Unlock();
}
mutex_h323.Wait();
break;
case MESSAGE_DISCONNECT: /* call has been disconnected */
#if 0
PDEBUG(DEBUG_H323, "H323Port(%s) h323 port with (caller id %s) received disconnect cause=%d\n", p_name, p_callerinfo.id, param->disconnectinfo.cause);
/* we just play what we hear from the remote site */
if (p_state == PORT_STATE_IN_OVERLAP
|| p_state == PORT_STATE_IN_PROCEEDING)
{
/* copy connected information */
memcpy(&p_connectinfo, &param->connectinfo, sizeof(p_connectinfo));
UCPY(name, p_name);
mutex_h323.Signal();
connection = h323_ep->FindConnectionWithLock(name);
if (connection)
{
connection->AnsweringCall(H323Connection::AnswerCallNow);
connection->Unlock();
}
mutex_h323.Wait();
}
new_state(PORT_STATE_DISCONNECT);
break;
#endif
case MESSAGE_RELEASE: /* release h323 port */
PDEBUG(DEBUG_H323, "H323Port(%s) h323 port with (caller id %s) received disconnect cause=%d\n", p_name, p_callerinfo.id, param->disconnectinfo.cause);
if (p_state != PORT_STATE_IN_OVERLAP
&& p_state != PORT_STATE_IN_PROCEEDING
&& p_state != PORT_STATE_IN_ALERTING
&& p_state != PORT_STATE_OUT_SETUP
&& p_state != PORT_STATE_OUT_OVERLAP
&& p_state != PORT_STATE_OUT_PROCEEDING
&& p_state != PORT_STATE_OUT_ALERTING
&& p_state != PORT_STATE_CONNECT)
{
PERROR("H323Port(%s) disconnect command only possible in setup, proceeding, alerting or connect state.\n", p_name);
break;
}
switch(param->disconnectinfo.cause)
{
case 1:
h323_cause = H323Connection::EndedByNoUser;
break;
case 2:
case 3:
case 5:
h323_cause = H323Connection::EndedByUnreachable;
break;
case 17:
h323_cause = H323Connection::EndedByRemoteBusy;
break;
case 18:
h323_cause = H323Connection::EndedByNoEndPoint;
break;
case 19:
h323_cause = H323Connection::EndedByNoAnswer;
break;
case 21:
h323_cause = H323Connection::EndedByRefusal;
break;
case 27:
h323_cause = H323Connection::EndedByHostOffline;
break;
case 47:
h323_cause = H323Connection::EndedByConnectFail;
break;
case 65:
h323_cause = H323Connection::EndedByCapabilityExchange;
break;
case 42:
h323_cause = H323Connection::EndedByRemoteCongestion;
break;
case 41:
h323_cause = H323Connection::EndedByTemporaryFailure;
break;
default:
h323_cause = H323Connection::EndedByRemoteUser;
break;
}
UCPY(name, p_name);
mutex_h323.Signal();
h323_ep->ClearCall(name, h323_cause);
mutex_h323.Wait();
delete this;
break;
case MESSAGE_SETUP: /* dial-out command received from epoint */
PDEBUG(DEBUG_H323, "H323Port(%s) h323 port received setup from '%s' to '%s'\n", p_name, param->setup.callerinfo.id, param->setup.dialinginfo.number);
if (p_type!=PORT_TYPE_H323_OUT)
{
PERROR("H323Port(%s) cannot dial because h323 port not of outgoing type.\n", p_name);
break;
}
if (p_state != PORT_STATE_IDLE)
{
PERROR("H323Port(%s) error: dialing command only possible in idle state.\n", p_name);
break;
}
/* link relation */
if (p_epointlist)
{
PERROR("H323Port(%s) software error: epoint pointer is set in idle state, how bad!! exitting.\n", p_name);
exit(-1);
}
if (!(epointlist_new(epoint_id)))
{
PERROR("no memory for epointlist\n");
exit(-1);
}
/* copy setup infos to port */
memcpy(&p_callerinfo, &param->setup.callerinfo, sizeof(p_callerinfo));
memcpy(&p_dialinginfo, &param->setup.dialinginfo, sizeof(p_dialinginfo));
memcpy(&p_capainfo, &param->setup.capainfo, sizeof(p_capainfo));
memcpy(&p_redirinfo, &param->setup.redirinfo, sizeof(p_redirinfo));
p_state = PORT_STATE_OUT_SETUP;
UCPY(name, p_name);
mutex_h323.Signal();
h323_ep->Call(name, param->setup.callerinfo.id, param->setup.dialinginfo.number);
mutex_h323.Wait();
break;
default:
PDEBUG(DEBUG_H323, "H323Port(%s) h323 port with (caller id %s) received an unsupported message: %d\n", p_name, p_callerinfo.id, message_id);
}
return(1);
}

27
h323.h
View File

@ -1,27 +0,0 @@
/*****************************************************************************\
** **
** PBX4Linux **
** **
**---------------------------------------------------------------------------**
** Copyright: Andreas Eversberg **
** **
** h323-port header file **
** **
\*****************************************************************************/
/* h323 port class */
class H323_chan;
class H323Port : public Port
{
public:
H323Port(int type, char *portname, struct port_settings *settings);
~H323Port();
int message_epoint(unsigned long epoint_id, int message, union parameter *param);
H323_chan *p_h323_channel_in; /* channels of port */
H323_chan *p_h323_channel_out;
void *p_h323_connect; /* q931 object of connect PDU */
};

View File

@ -1,189 +0,0 @@
///////////////////////////////////////////////////////////////////////////////
// //
// PBX4Linux //
// //
//---------------------------------------------------------------------------//
// Copyright: Andreas Eversberg //
// //
// H323_chan class //
// //
///////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include "main.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>
//
// constructor
//
H323_chan::H323_chan(const PString &token, BOOL isEncoding) : PIndirectChannel()
{
d_token = token;
// d_isEncoding = isEncoding;
PDEBUG(DEBUG_H323, "H323 channel constuctor of channel (%scoding)\n", (isEncoding)?"en":"de");
transfering = FALSE;
}
//
// destructor
//
H323_chan::~H323_chan(void)
{
PDEBUG(DEBUG_H323, "H323 channel destuctor\n");
}
//
// Closes the
//
BOOL H323_chan::Close(void)
{
PDEBUG(DEBUG_H323, "H323 channel Close\n");
return TRUE;
}
//
// IsOpen
//
BOOL H323_chan::IsOpen(void) const
{
PDEBUG(DEBUG_H323, "H323 channel IsOpen\n");
return TRUE;
}
//
// Read
//
BOOL H323_chan::Read(void *buf, PINDEX len)
{
int nr_words;
class H323Port *port;
const unsigned char *token_string = d_token;
PTime Now;
PTimeInterval diff;
nr_words = len/2;
// cout << "H323 channel Read " << nr_words << " words" << endl;
mutex_h323.Wait();
if (!(port = (class H323Port *)find_port_with_token((char *)token_string)))
{
PERROR("H323 channel Read() cannot find port with token %s\n", token_string);
mutex_h323.Signal();
lastReadCount = 0;
return FALSE;
}
nr_words = port->read_audio((unsigned char *)buf, nr_words, 0);
mutex_h323.Signal();
// delay
if (!transfering)
{
PDEBUG(DEBUG_H323, "H323 channel Read(%s) sending to h323 the first time\n", token_string);
start = Now;
transfering = TRUE;
elapsed = 0;
}
diff = Now-start;
elapsed += nr_words*125;
if (elapsed > (diff.GetMilliSeconds()*1000))
usleep(elapsed - (diff.GetMilliSeconds()*1000));
lastReadCount = 2 * nr_words;
return TRUE;
}
//
// Write
//
BOOL H323_chan::Write(const void *buf, PINDEX len)
{
int nr_words;
class H323Port *port;
const unsigned char *token_string = d_token;
PTime Now;
PTimeInterval diff;
unsigned char *data_temp;
unsigned long length_temp;
struct message *message;
nr_words = len / 2;
// cout << "H323 channel Write " << nr_words << " words" << endl;
mutex_h323.Wait();
if (!(port = (class H323Port *)find_port_with_token((char *)token_string)))
{
PERROR("H323 channel Write() cannot find port with token %s\n", token_string);
mutex_h323.Signal();
lastReadCount = 0;
return FALSE;
}
// send data message
length_temp = len;
data_temp = (unsigned char *)buf;
while(length_temp)
{
message = message_create(port->p_serial, ACTIVE_EPOINT(port->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->param.data.compressed = 0;
/* { // testin with law data
int i=0;
while (i<message->param.data.len)
{
((unsigned char *)message->param.data.data)[i] = audio_s16_to_law[((signed short*)data_temp)[i] & 0xffff];
i++;
}
}
message->param.data.len = message->param.data.len/2;
message->param.data.compressed = 1;
*/
message->param.data.port_type = port->p_type;
message->param.data.port_id = port->p_serial;
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);
}
mutex_h323.Signal();
// delay
if (!transfering)
{
PDEBUG(DEBUG_H323, "H323 channel Write(%s) receiving from h323 the first time\n", token_string);
start = Now;
transfering = TRUE;
elapsed = 0;
}
diff = Now-start;
elapsed += nr_words*125;
if (elapsed > (diff.GetMilliSeconds()*1000))
usleep(elapsed - (diff.GetMilliSeconds()*1000));
lastWriteCount = 2 * nr_words;
return TRUE;
}

View File

@ -1,34 +0,0 @@
///////////////////////////////////////////////////////////////////////////////
// //
// PBX4Linux //
// //
//---------------------------------------------------------------------------//
// Copyright: Andreas Eversberg //
// //
// h323_chan header file //
// //
///////////////////////////////////////////////////////////////////////////////
#ifndef H323_CHAN_HEADER
#define H323_CHAN_HEADER
class H323_chan : public PIndirectChannel
{
public:
H323_chan(const PString &token, BOOL isEncoding);
~H323_chan(void);
BOOL Close(void);
BOOL IsOpen(void) const;
BOOL Read(void *buf, PINDEX len);
BOOL Write(const void *buf, PINDEX len);
private:
PString d_token;
PTime start;
BOOL transfering;
PInt64 elapsed;
};
#endif

View File

@ -1,648 +0,0 @@
///////////////////////////////////////////////////////////////////////////////
// //
// PBX4Linux //
// //
//---------------------------------------------------------------------------//
// Copyright: Andreas Eversberg //
// //
// h323_con connection class //
// //
///////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include "main.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>
//
// constructor
//
H323_con::H323_con(H323_ep &endpoint, unsigned callReference) : H323Connection(endpoint, callReference)
{
PDEBUG(DEBUG_H323, "H323 connection constuctor\n");
SetAudioJitterDelay(0, 0);
}
//
// destructor
//
H323_con::~H323_con()
{
class H323Port *port;
const unsigned char *token_string = callToken;
struct message *message;
mutex_h323.Wait();
// get ioport
port = (class H323Port *)find_port_with_token((char *)token_string);
if (!port)
{
PERROR("no port with token '%s'\n", token_string);
} else
{
/* sending release (if not already) */
message = message_create(port->p_serial, ACTIVE_EPOINT(port->p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
message->param.disconnectinfo.cause = 16;
message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
message_put(message);
}
mutex_h323.Signal();
PDEBUG(DEBUG_H323, "H323 connection destuctor\n");
}
//
// AnswerCallResponse (incoming call)
//
H323Connection::AnswerCallResponse H323_con::OnAnswerCall(const PString &, const H323SignalPDU &setupPDU, H323SignalPDU &connectPDU)
{
class H323Port *port;
const char *calleraddress;
char callerip[32], *extension;
const char *dialing = NULL;
const H225_Setup_UUIE &setup = setupPDU.m_h323_uu_pdu.m_h323_message_body;
const H225_ArrayOf_AliasAddress &adr = setup.m_destinationAddress;
PINDEX i;
const unsigned char *token_string = callToken;
struct message *message;
class Endpoint *epoint;
const Q931 setup_q931 = setupPDU.GetQ931();
PString calling_number;
PString redir_number;
unsigned type, plan, present, screen, reason;
struct caller_info *callerinfo;
struct dialing_info *dialinginfo;
struct capa_info *capainfo;
struct redir_info *redirinfo;
char option[64] = "";
PDEBUG(DEBUG_H323, "H323 connection incoming call\n");
mutex_h323.Wait();
// alloc new h323 port structure
if (!(port = new H323Port(PORT_TYPE_H323_IN, (char *)token_string, NULL)))
{
mutex_h323.Signal();
return AnswerCallDenied;
}
callerinfo = &port->p_callerinfo;
redirinfo = &port->p_redirinfo;
capainfo = &port->p_capainfo;
dialinginfo = &port->p_dialinginfo;
memset(callerinfo, 0, sizeof(struct caller_info));
memset(redirinfo, 0, sizeof(struct redir_info));
memset(capainfo, 0, sizeof(struct capa_info));
memset(dialinginfo, 0, sizeof(struct dialing_info));
callerinfo->itype = INFO_ITYPE_H323;
// get calling party information
if (setup_q931.GetCallingPartyNumber(calling_number, &plan, &type, &present, &screen))
{
SCPY(callerinfo->id, calling_number.GetPointer());
switch (present)
{
case 1:
callerinfo->present = INFO_PRESENT_RESTRICTED;
break;
case 2:
callerinfo->present = INFO_PRESENT_NOTAVAIL;
break;
default:
callerinfo->present = INFO_PRESENT_ALLOWED;
break;
}
switch (type)
{
case Q931::InternationalType:
callerinfo->ntype = INFO_NTYPE_INTERNATIONAL;
break;
case Q931::NationalType:
callerinfo->ntype = INFO_NTYPE_NATIONAL;
break;
case Q931::SubscriberType:
callerinfo->ntype = INFO_NTYPE_SUBSCRIBER;
break;
default:
callerinfo->ntype = INFO_NTYPE_UNKNOWN;
break;
}
switch (screen)
{
case 0:
callerinfo->screen = INFO_SCREEN_USER;
break;
default:
callerinfo->screen = INFO_SCREEN_NETWORK;
break;
}
}
redirinfo->itype = INFO_ITYPE_H323;
// get redirecting number information
if (setup_q931.GetRedirectingNumber(redir_number, &plan, &type, &present, &screen, &reason))
{
SCPY(redirinfo->id, redir_number.GetPointer());
switch (present)
{
case 1:
redirinfo->present = INFO_PRESENT_RESTRICTED;
break;
case 2:
redirinfo->present = INFO_PRESENT_NOTAVAIL;
break;
default:
redirinfo->present = INFO_PRESENT_ALLOWED;
break;
}
switch (type)
{
case Q931::InternationalType:
redirinfo->ntype = INFO_NTYPE_INTERNATIONAL;
break;
case Q931::NationalType:
redirinfo->ntype = INFO_NTYPE_NATIONAL;
break;
case Q931::SubscriberType:
redirinfo->ntype = INFO_NTYPE_SUBSCRIBER;
break;
default:
redirinfo->ntype = INFO_NTYPE_UNKNOWN;
break;
}
switch (screen)
{
case 0:
redirinfo->screen = INFO_SCREEN_USER;
break;
default:
redirinfo->screen = INFO_SCREEN_NETWORK;
break;
}
switch (reason)
{
case 1:
redirinfo->reason = INFO_REDIR_BUSY;
break;
case 2:
redirinfo->reason = INFO_REDIR_NORESPONSE;
break;
case 15:
redirinfo->reason = INFO_REDIR_UNCONDITIONAL;
break;
case 10:
redirinfo->reason = INFO_REDIR_CALLDEFLECT;
break;
case 9:
redirinfo->reason = INFO_REDIR_OUTOFORDER;
break;
default:
redirinfo->reason = INFO_REDIR_UNKNOWN;
break;
}
}
// get remote party h323-address information
calleraddress = GetRemotePartyAddress();
callerip[0] = '\0';
if (calleraddress)
{
if (strstr(calleraddress, "ip$"))
{
SCPY(callerip, strstr(calleraddress, "ip$")+3);
if (strchr(callerip, ':'))
*strchr(callerip, ':') = '\0';
memmove(strstr(calleraddress, "ip$"), strstr(calleraddress, "ip$")+3, strlen(strstr(calleraddress, "ip$")+3)+1);
}
if (strchr(calleraddress, ':'))
*strchr(calleraddress, ':') = '\0';
}
// get dialing information
for(i=0; i<adr.GetSize(); i++)
if (adr[i].GetTag() == H225_AliasAddress::e_dialedDigits)
dialing = H323GetAliasAddressString(adr[i]);
if (!dialing)
dialing = "";
// fill port's information
if (calleraddress)
SCPY(callerinfo->voip, (char *)calleraddress);
capainfo->bearer_mode = INFO_BMODE_CIRCUIT;
capainfo->bearer_info1 = (options.law=='u')?INFO_INFO1_ULAW:INFO_INFO1_ALAW;
capainfo->bearer_capa = INFO_BC_SPEECH;
// change to incoming setup state
port->new_state(PORT_STATE_IN_OVERLAP);
// allocate new endpoint
if (!(epoint = new Endpoint(port->p_serial, 0)))
{
// error allocating endpoint
PDEBUG(DEBUG_H323, "h323-connection(%s) rejecting call because cannot create epoint for '%s'\n", port->p_name, callerinfo->id);
delete port;
port = NULL;
mutex_h323.Signal();
return AnswerCallDenied;
}
if (!(epoint->ep_app = new DEFAULT_ENDPOINT_APP(epoint)))
{
PERROR("no memory for application\n");
exit(-1);
}
if (!(port->epointlist_new(epoint->ep_serial)))
{
PERROR("no memory for epointlist\n");
exit(-1);
}
port->set_tone(NULL, "");
// send setup message to endpoint
message = message_create(port->p_serial, ACTIVE_EPOINT(port->p_epointlist), PORT_TO_EPOINT, MESSAGE_SETUP);
message->param.setup.port_type = port->p_type;
// before we start, we may check for h323_gateway entry
if (callerip[0])
{
extension = parse_h323gateway(callerip, option, sizeof(option));
if (extension)
{
PDEBUG(DEBUG_H323, "h323-connection(%s) gateway '%s' is mapped to extension '%s' (option= '%s')\n", port->p_name, callerip, extension, option);
SCPY(callerinfo->id, extension);
SCPY(callerinfo->intern, extension);
callerinfo->itype = INFO_ITYPE_INTERN;
callerinfo->screen = INFO_SCREEN_NETWORK;
} else
{
PDEBUG(DEBUG_H323, "h323-connection(%s) gateway '%s' is not mapped to any extension. (port_type=0x%x)\n", port->p_name, callerip, port->p_type);
// get the default dialing external dialing string
}
}
// default dialing for extenal calls
if (!callerinfo->intern[0] && !dialing[0])
dialing = options.h323_icall_prefix;
// dialing information
if (callerip[0] || dialing[0])
{
SCPY(dialinginfo->number, (char *)dialing);
dialinginfo->ntype = INFO_NTYPE_UNKNOWN;
}
memcpy(&message->param.setup.callerinfo, callerinfo, sizeof(struct caller_info));
memcpy(&message->param.setup.dialinginfo, dialinginfo, sizeof(struct dialing_info));
memcpy(&message->param.setup.redirinfo, redirinfo, sizeof(struct redir_info));
memcpy(&message->param.setup.capainfo, capainfo, sizeof(struct capa_info));
message->param.setup.dtmf = 1;
message_put(message);
port->p_h323_connect = &(connectPDU.GetQ931());
mutex_h323.Signal();
if (!strcasecmp(option, "connect") || !strcasecmp(option, "dtmf"))
{
port->new_state(PORT_STATE_CONNECT);
return AnswerCallNow;
} else
{
return AnswerCallDeferred;
}
}
//
// OnOutgoingCall (outgoing call)
//
BOOL H323_con::OnOutgoingCall(const H323SignalPDU &connectPDU)
{
class H323Port *port;
const char *calleraddress;
char callerip[32];
const unsigned char *token_string = callToken;
struct message *message;
// H225_Connect_UUIE &connect_uuie = connectPDU.m_h323_uu_pdu.m_h323_message_body;
const Q931 connect_q931 = connectPDU.GetQ931();
PString connect_number;
unsigned type = 0, plan = 0, present = 0, screen = 0;
struct connect_info *connectinfo;
PDEBUG(DEBUG_H323, "H323 connection outgoing call is connected.\n");
mutex_h323.Wait();
if (!(port = (class H323Port *)find_port_with_token((char *)token_string)))
{
PERROR(" cannot find port with token '%s'\n", token_string);
mutex_h323.Signal();
return FALSE;
}
connectinfo = &port->p_connectinfo;
if (port->p_type == PORT_TYPE_H323_IN)
{
PDEBUG(DEBUG_H323, "H323 endpoint OnConnectionEstablished() incoming port\n");
}
if (port->p_type == PORT_TYPE_H323_OUT)
{
PDEBUG(DEBUG_H323, "H323 endpoint OnConnectionEstablished() outgoing port\n");
if (port->p_state==PORT_STATE_OUT_SETUP
|| port->p_state==PORT_STATE_OUT_OVERLAP
|| port->p_state==PORT_STATE_OUT_PROCEEDING
|| port->p_state==PORT_STATE_OUT_ALERTING)
{
// get remote party h323-address information
calleraddress = GetRemotePartyAddress();
callerip[0] = '\0';
if (calleraddress)
{
if (strchr(calleraddress, '$'))
{
SCPY(callerip, strchr(calleraddress, '$'));
callerip[sizeof(callerip)-1] = '\0';
if (strchr(callerip, ':'))
*strchr(callerip, ':') = '\0';
}
SCPY(connectinfo->voip, (char *)calleraddress);
}
// get COLP
memset(connectinfo, 0, sizeof(struct connect_info));
connectinfo->itype = INFO_ITYPE_H323;
if (connect_q931.GetConnectedNumber(connect_number, &plan, &type, &present, &screen))
{
SCPY(connectinfo->id, connect_number.GetPointer());
switch (present)
{
case 1:
connectinfo->present = INFO_PRESENT_RESTRICTED;
break;
case 2:
connectinfo->present = INFO_PRESENT_NOTAVAIL;
break;
default:
connectinfo->present = INFO_PRESENT_ALLOWED;
}
switch (type)
{
case Q931::InternationalType:
connectinfo->ntype = INFO_NTYPE_INTERNATIONAL;
break;
case Q931::NationalType:
connectinfo->ntype = INFO_NTYPE_NATIONAL;
break;
case Q931::SubscriberType:
connectinfo->ntype = INFO_NTYPE_SUBSCRIBER;
break;
default:
connectinfo->ntype = INFO_NTYPE_UNKNOWN;
}
switch (screen)
{
case 0:
connectinfo->screen = INFO_SCREEN_USER;
break;
default:
connectinfo->screen = INFO_SCREEN_NETWORK;
}
}
port->new_state(PORT_STATE_CONNECT);
message = message_create(port->p_serial, ACTIVE_EPOINT(port->p_epointlist), PORT_TO_EPOINT, MESSAGE_CONNECT);
memcpy(&message->param.connectinfo, connectinfo, sizeof(struct connect_info));
message_put(message);
}
}
mutex_h323.Signal();
return H323Connection::OnOutgoingCall(connectPDU);
}
//
// send setup information to the called h323 user
//
BOOL H323_con::OnSendSignalSetup(H323SignalPDU &setupPDU)
{
H225_Setup_UUIE &setup = setupPDU.m_h323_uu_pdu.m_h323_message_body;
H225_ArrayOf_AliasAddress &adr = setup.m_sourceAddress;
H225_AliasAddress new_alias;
PString calling_number;
PString calling_alias;
PString dialing_number;
PString redir_number;
int type, present, screen, reason;
class H323Port *port;
const unsigned char *token_string = callToken;
struct caller_info *callerinfo;
struct dialing_info *dialinginfo;
struct capa_info *capainfo;
struct redir_info *redirinfo;
mutex_h323.Wait();
if (!(port = (class H323Port *)find_port_with_token((char *)token_string)))
{
PERROR(" no port with token '%s'\n", token_string);
mutex_h323.Signal();
return FALSE;
}
callerinfo = &port->p_callerinfo;
redirinfo = &port->p_redirinfo;
capainfo = &port->p_capainfo;
dialinginfo = &port->p_dialinginfo;
PDEBUG(DEBUG_H323, "H323-connection sending modified setup signal '%s'->'%s'\n", callerinfo->id, dialinginfo->number);
if (callerinfo->present!=INFO_PRESENT_NULL)
{
calling_alias = numberrize_callerinfo(callerinfo->id, callerinfo->ntype);
H323SetAliasAddress(calling_alias, new_alias);
adr.SetSize(adr.GetSize()+1);
adr[adr.GetSize()-1] = new_alias;
calling_number = callerinfo->id;
switch(callerinfo->ntype)
{
case INFO_NTYPE_SUBSCRIBER:
type = Q931::SubscriberType;
break;
case INFO_NTYPE_NATIONAL:
type = Q931::NationalType;
break;
case INFO_NTYPE_INTERNATIONAL:
type = Q931::InternationalType;
break;
default: /* INFO_NTYPE_UNKNOWN */
type = Q931::UnknownType;
}
switch(callerinfo->present)
{
case INFO_PRESENT_RESTRICTED:
present = 1;
break;
case INFO_PRESENT_NOTAVAIL:
present = 2;
break;
default: /* INFO_PRESENT_ALLOWED */
present = 0;
}
switch(callerinfo->screen)
{
case INFO_SCREEN_USER:
screen = 0;
break;
default: /* INFO_SCREEN_NETWORK */
screen = 3;
}
Q931 &new_q931 = setupPDU.GetQ931();
new_q931.SetCallingPartyNumber(calling_number, Q931::ISDNPlan, type, present, screen);
}
if (redirinfo->present!=INFO_PRESENT_NULL)
{
if (redirinfo->present==INFO_PRESENT_ALLOWED)
{
redir_number = callerinfo->id;
} else
redir_number = "";
switch(redirinfo->ntype)
{
case INFO_NTYPE_SUBSCRIBER:
type = Q931::SubscriberType;
break;
case INFO_NTYPE_NATIONAL:
type = Q931::NationalType;
break;
case INFO_NTYPE_INTERNATIONAL:
type = Q931::InternationalType;
break;
default: /* INFO_TYPE_UNKNOWN */
type = Q931::UnknownType;
}
switch(redirinfo->present)
{
case INFO_PRESENT_RESTRICTED:
present = 1;
break;
case INFO_PRESENT_NOTAVAIL:
present = 2;
break;
default: /* INFO_PRESENT_ALLOWED */
present = 0;
}
switch(redirinfo->reason)
{
case INFO_REDIR_BUSY:
reason = 1;
break;
case INFO_REDIR_NORESPONSE:
reason = 2;
break;
case INFO_REDIR_UNCONDITIONAL:
reason = 15;
break;
case INFO_REDIR_OUTOFORDER:
reason = 9;
break;
case INFO_REDIR_CALLDEFLECT:
reason = 10;
break;
default: /* INFO_REDIR_UNKNOWN */
reason = 0;
}
Q931 &new_q931 = setupPDU.GetQ931();
new_q931.SetRedirectingNumber(redir_number, Q931::ISDNPlan, type, present, screen, reason);
}
if (dialinginfo->number[0])
{
dialing_number = dialinginfo->number;
Q931 &new_q931 = setupPDU.GetQ931();
new_q931.SetCalledPartyNumber(dialing_number);
}
mutex_h323.Signal();
return H323Connection::OnSendSignalSetup(setupPDU);
}
//
// callback for start of channel
//
BOOL H323_con::OnStartLogicalChannel(H323Channel &channel)
{
if (!H323Connection::OnStartLogicalChannel(channel))
{
PERROR("starting logical channel failed!\n");
return FALSE;
}
PDEBUG(DEBUG_H323, "H323 connection starting logical channel using \"%s\" codec %s :%s\n",
channel.GetCapability().GetFormatName().GetPointer(),
(channel.GetDirection()==H323Channel::IsTransmitter)?"transmit":"receive",
callToken.GetPointer());
return H323Connection::OnStartLogicalChannel(channel);
}
//
// user input received
//
void H323_con::OnUserInputString (const PString &value)
{
class H323Port *port;
const unsigned char *token_string = callToken;
const unsigned char *value_string = value;
struct message *message;
PDEBUG(DEBUG_H323, "H323-connection received user input'%s'\n", value_string);
mutex_h323.Wait();
if (!(port = (class H323Port *)find_port_with_token((char *)token_string)))
{
PERROR("no port with token '%s'\n", token_string);
} else
{
while(*value_string)
{
message = message_create(port->p_serial, ACTIVE_EPOINT(port->p_epointlist), PORT_TO_EPOINT, MESSAGE_DTMF);
message->param.dtmf = *value_string++;
message_put(message);
}
#if 0
message = message_create(port->p_serial, ACTIVE_EPOINT(port->p_epointlist), PORT_TO_EPOINT, MESSAGE_INFORMATION);
SCPY(message->param.information.number, (char *)value_string);
message_put(message);
#endif
}
mutex_h323.Signal();
}

View File

@ -1,35 +0,0 @@
///////////////////////////////////////////////////////////////////////////////
// //
// PBX4Linux //
// //
//---------------------------------------------------------------------------//
// Copyright: Andreas Eversberg //
// //
// h323_con connection header file //
// //
///////////////////////////////////////////////////////////////////////////////
#ifndef H323_CON_HEADER
#define H323_CON_HEADER
class H323_chan;
class H323_con : public H323Connection
{
public:
H323_con(H323_ep &endpoint, unsigned callReference);
~H323_con();
AnswerCallResponse OnAnswerCall(const PString &, const H323SignalPDU &, H323SignalPDU &);
BOOL OnOutgoingCall(const H323SignalPDU &connectPDU);
BOOL OnSendSignalSetup(H323SignalPDU &);
BOOL OnStartLogicalChannel(H323Channel &channel);
void OnUserInputString (const PString &value);
H323SignalPDU *GetConnectPDU(void);
private:
};
#endif // H323_CON_HEADER

View File

@ -1,503 +0,0 @@
///////////////////////////////////////////////////////////////////////////////
// //
// PBX4Linux //
// //
//---------------------------------------------------------------------------//
// Copyright: Andreas Eversberg //
// //
// h323_ep class //
// //
///////////////////////////////////////////////////////////////////////////////
/*
NOTE:
The code was inspired by the isdn2h323 gateway my marco bode.
Thanx to marco budde for lerarning to program h323 and c++ from your code.
His homepage is www.telos.de, there you'll find the isdn2h323 gateway.
Also thanx to others who write documents and applications for OpenH323.
Andreas Eversberg
*/
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include "main.h"
//#include <gsmcodec.h>
//#include <g7231codec.h>
//#include <g729codec.h>
//#include "g726codec.h"
//#include <speexcodec.h>
#include <cstdio>
#include <cstdlib>
#include <cstring>
//
// constructor
//
H323_ep::H323_ep(void)
{
terminalType = e_GatewayOnly;
PDEBUG(DEBUG_H323, "H323 endpoint constuctor\n");
}
//
// destructor
//
H323_ep::~H323_ep()
{
// clear all calls to remote endpoints
ClearAllCalls();
PDEBUG(DEBUG_H323, "H323 endpoint destuctor\n");
}
//
// create connection
//
H323Connection *H323_ep::CreateConnection(unsigned callReference)
{
PDEBUG(DEBUG_H323, "H323 endpoint create connection\n");
return new H323_con(*this, callReference);
}
//
// on establishment of conneciton
//
void H323_ep::OnConnectionEstablished(H323Connection &connection, const PString &token)
{
const unsigned char *token_string = token;
PDEBUG(DEBUG_H323, "H323 endpoint connection established to: %s\n", token_string);
H323EndPoint::OnConnectionEstablished(connection, token);
}
//
// on remote alerting
//
BOOL H323_ep::OnAlerting(H323Connection &connection, const H323SignalPDU &alertingPDU, const PString &user)
{
class H323Port *port;
const unsigned char *token_string = connection.GetCallToken();
const unsigned char *user_string = user;
struct message *message;
PDEBUG(DEBUG_H323, "H323 endpoint alerting at: %s\n", user_string);
mutex_h323.Wait();
if (!(port=(class H323Port *)find_port_with_token((char *)token_string)))
{
PERROR("cannot find port with token '%s'\n", token_string);
mutex_h323.Signal();
return FALSE;
}
if (port->p_state==PORT_STATE_OUT_SETUP
|| port->p_state==PORT_STATE_OUT_OVERLAP
|| port->p_state==PORT_STATE_OUT_PROCEEDING)
{
port->new_state(PORT_STATE_OUT_ALERTING);
message = message_create(port->p_serial, ACTIVE_EPOINT(port->p_epointlist), PORT_TO_EPOINT, MESSAGE_ALERTING);
message_put(message);
}
mutex_h323.Signal();
return TRUE;
}
//
// on clearing of connection
//
void H323_ep::OnConnectionCleared(H323Connection &connection, const PString &token)
{
int cause;
class H323Port *port;
const unsigned char *token_string = token;
struct message *message;
PDEBUG(DEBUG_H323, "H323 endpoint connection cleared.\n");
mutex_h323.Wait();
if (!(port=(class H323Port *)find_port_with_token((char *)token_string)))
{
PERROR("cannot find port with token '%s'\n", token_string);
mutex_h323.Signal();
return;
}
switch(connection.GetCallEndReason())
{
case H323Connection::EndedByRemoteUser:
case H323Connection::EndedByCallerAbort:
case H323Connection::EndedByGatekeeper:
case H323Connection::EndedByCallForwarded:
cause = 16; // normal call clearing
break;
case H323Connection::EndedByRefusal:
case H323Connection::EndedBySecurityDenial:
cause = 21; // call rejected
break;
case H323Connection::EndedByNoAnswer:
cause = 19; // no answer from user
break;
case H323Connection::EndedByTransportFail:
cause = 47; // resource unavaiable, unspecified
break;
case H323Connection::EndedByNoBandwidth:
cause = 49; // quality of service not available
break;
case H323Connection::EndedByNoUser:
cause = 1; // unallocated number
break;
case H323Connection::EndedByCapabilityExchange:
cause = 65; // bearer capability not implemented
break;
case H323Connection::EndedByRemoteBusy:
cause = 17; // user busy
break;
case H323Connection::EndedByRemoteCongestion:
cause = 42; // switching equipment congestion
break;
case H323Connection::EndedByUnreachable:
cause = 2; // no route ...
break;
case H323Connection::EndedByNoEndPoint:
case H323Connection::EndedByConnectFail:
cause = 18; // no user responding
break;
case H323Connection::EndedByHostOffline:
cause = 27; // destination out of order
break;
case H323Connection::EndedByTemporaryFailure:
cause = 41; // temporary failure
break;
default:
cause = 31; // normal, unspecified
break;
}
// delete channels
if (port->p_h323_channel_in)
delete port->p_h323_channel_in;
port->p_h323_channel_in = NULL;
if (port->p_h323_channel_out)
delete port->p_h323_channel_out;
port->p_h323_channel_out = NULL;
/* release endpoint */
message = message_create(port->p_serial, ACTIVE_EPOINT(port->p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
message->param.disconnectinfo.cause = cause;
message->param.disconnectinfo.location = LOCATION_BEYOND;
message_put(message);
/* delete port */
delete port;
mutex_h323.Signal();
}
//
// open audio channel
//
BOOL H323_ep::OpenAudioChannel(H323Connection &connection, BOOL isEncoding, unsigned bufferSize, H323AudioCodec &codec)
{
H323_chan *channel;
class H323Port *port;
const unsigned char *token_string = connection.GetCallToken();
PDEBUG(DEBUG_H323, "H323 endpoint audio channel open (isEndcoding=%d).\n", isEncoding);
// disable the silence detection
codec.SetSilenceDetectionMode (H323AudioCodec::NoSilenceDetection);
// create channels
if (isEncoding)
{
channel = new H323_chan(connection.GetCallToken(), TRUE);
} else
{
channel = new H323_chan(connection.GetCallToken(), FALSE);
}
if (!channel)
{
PERROR("channel for token '%s' not set", token_string);
return FALSE;
}
// return the channel object
mutex_h323.Wait();
if (!(port=(class H323Port *)find_port_with_token((char *)token_string)))
{
PERROR("cannot find port with token '%s'\n", token_string);
mutex_h323.Signal();
return FALSE;
}
// set channels
if (isEncoding)
{
port->p_h323_channel_out = channel;
} else
{
port->p_h323_channel_in = channel;
}
mutex_h323.Signal();
return codec.AttachChannel(channel, FALSE);
}
//
// open video channel
//
BOOL H323_ep::OpenVideoChannel(H323Connection &connection, BOOL isEncoding, H323VideoCodec &codec)
{
PDEBUG(DEBUG_H323, "H323 endpoint video channel open (isEndcoding=%d).\n", isEncoding);
return FALSE;
}
//
// initialize H323 endpoint
//
BOOL H323_ep::Init(void)
{
H323ListenerTCP *listener;
int pri;
PDEBUG(DEBUG_H323, "H323 endpoint initialize\n");
// add keypad capability
H323_UserInputCapability::AddAllCapabilities(capabilities, 0, P_MAX_INDEX);
/* will add codec in order of priority 1 = highest, 0 = don't use */
pri = 1;
while (pri < 256)
{
#warning codecs are temporarily disabled due to api change
#if 0
if (options.h323_gsm_pri == pri)
{
H323_GSM0610Capability * gsm_cap;
MicrosoftGSMAudioCapability * msgsm_cap;
SetCapability(0, 0, gsm_cap = new H323_GSM0610Capability);
gsm_cap->SetTxFramesInPacket(options.h323_gsm_opt);
SetCapability(0, 0, msgsm_cap = new MicrosoftGSMAudioCapability);
msgsm_cap->SetTxFramesInPacket(options.h323_gsm_opt);
}
if (options.h323_g726_pri == pri)
{
if (options.h323_g726_opt > 4)
SetCapability(0, 0, new H323_G726_Capability(*this, H323_G726_Capability::e_40k));
if (options.h323_g726_opt > 3)
SetCapability(0, 0, new H323_G726_Capability(*this, H323_G726_Capability::e_32k));
if (options.h323_g726_opt > 2)
SetCapability(0, 0, new H323_G726_Capability(*this, H323_G726_Capability::e_24k));
SetCapability(0, 0, new H323_G726_Capability(*this, H323_G726_Capability::e_16k));
}
if (options.h323_g7231_pri == pri)
{
#if 0
SetCapability(0, 0, new H323_G7231Capability(FALSE));
#endif
}
if (options.h323_g729a_pri == pri)
{
#if 0
SetCapability(0, 0, new H323_G729Capability());
#endif
}
if (options.h323_lpc10_pri == pri)
{
SetCapability(0, 0, new H323_LPC10Capability(*this));
}
if (options.h323_speex_pri == pri)
{
if (options.h323_speex_opt > 5)
SetCapability(0, 0, new SpeexNarrow6AudioCapability());
if (options.h323_speex_opt > 4)
SetCapability(0, 0, new SpeexNarrow5AudioCapability());
if (options.h323_speex_opt > 3)
SetCapability(0, 0, new SpeexNarrow4AudioCapability());
if (options.h323_speex_opt > 2)
SetCapability(0, 0, new SpeexNarrow3AudioCapability());
SetCapability(0, 0, new SpeexNarrow2AudioCapability());
}
if (options.h323_xspeex_pri == pri)
{
if (options.h323_xspeex_opt > 5)
SetCapability(0, 0, new XiphSpeexNarrow6AudioCapability());
if (options.h323_xspeex_opt > 4)
SetCapability(0, 0, new XiphSpeexNarrow5AudioCapability());
if (options.h323_xspeex_opt > 3)
SetCapability(0, 0, new XiphSpeexNarrow4AudioCapability());
if (options.h323_xspeex_opt > 2)
SetCapability(0, 0, new XiphSpeexNarrow3AudioCapability());
SetCapability(0, 0, new XiphSpeexNarrow2AudioCapability());
}
#endif
if (options.h323_law_pri == pri)
{
H323_G711Capability * g711uCap;
H323_G711Capability * g711aCap;
SetCapability(0, 0, g711uCap = new H323_G711Capability (H323_G711Capability::ALaw/*, H323_G711Capability::At64k*/));
#warning H323_law frame size is disabled due to bug in OpenH323
// g711uCap->SetTxFramesInPacket(options.h323_law_opt);
SetCapability(0, 0, g711aCap = new H323_G711Capability (H323_G711Capability::muLaw/*, H323_G711Capability::At64k*/));
// g711aCap->SetTxFramesInPacket(options.h323_law_opt);
}
pri++;
}
// h323 user is the hostname or given by h323_name
if (options.h323_name[0] == '\0')
{
if (getenv("HOSTNAME") == NULL)
{
cout << "OpenH323: Environment variable HOSTNAME not set. Please specify 'h323_name' in options.conf" << endl;
return FALSE;
}
}
SetLocalUserName((options.h323_name[0])?options.h323_name:getenv("HOSTNAME"));
// create listener
if (options.h323_icall)
{
PIPSocket::Address interfaceAddress(INADDR_ANY);
listener = new H323ListenerTCP(*this, interfaceAddress, options.h323_port);
if (!StartListener(listener))
{
cout << "OpenH323: Could not open H323 port " << listener->GetListenerPort() << endl;
return FALSE;
}
cout << "OpenH323: Waiting for incoming H323 connections on port " << listener->GetListenerPort() << endl;
}
// register with gatekeeper
if (options.h323_gatekeeper)
{
if (options.h323_gatekeeper_host[0] == '\0')
{
if (DiscoverGatekeeper(new H323TransportUDP(*this)))
{
cout << "OpenH323: Registering with gatekeeper " << gatekeeper->GetIdentifier() << " (automatically)" << endl;
} else
{
cout << "OpenH323: Gatekeeper not found." << endl;
sleep(2);
}
} else
{
if (SetGatekeeper(options.h323_gatekeeper_host) == TRUE)
{
cout << "OpenH323: Registering with gatekeeper " << gatekeeper->GetIdentifier() << " (automatically)" << endl;
} else
{
cout << "OpenH323: Gatekeeper at " << gatekeeper->GetIdentifier() << " not found." << endl;
sleep(2);
}
}
}
return TRUE;
}
//
// make an outgoing h323 call
//
BOOL H323_ep::Call(char *token_string, char *caller, char *host)
{
PString address;
PString token = "";
BOOL failed = FALSE;
class H323Port *port;
struct message *message;
char *newtoken_string;
PDEBUG(DEBUG_H323, "H323 endpoint call to host '%s'\n", host);
address = host;
if (!MakeCall(address, token))
{
PDEBUG(DEBUG_H323, "H323 endpoint call to host '%s'\n", host);
failed = TRUE;
}
// set new token
mutex_h323.Wait();
if (!(port=(class H323Port *)find_port_with_token((char *)token_string)))
{
PERROR("cannot find port with token '%s'\n", token_string);
mutex_h323.Signal();
return FALSE;
}
if (failed == TRUE)
{
PDEBUG(DEBUG_H323, "call of port '%s' failed.\n", token_string);
message = message_create(port->p_serial, ACTIVE_EPOINT(port->p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
message->param.disconnectinfo.cause = 31;
message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
message_put(message);
} else
{
PDEBUG(DEBUG_H323, "changing port name from '%s' to token '%s'\n", token_string, token.GetPointer());
newtoken_string = token.GetPointer();
SCPY(port->p_name, newtoken_string);
}
mutex_h323.Signal();
PDEBUG(DEBUG_H323, "H323 endpoint call to host '%s'\n", host);
if (failed == TRUE)
return FALSE;
return TRUE;
}
void H323_ep::SetEndpointTypeInfo(H225_EndpointType &info) const
{
// H225_VoiceCaps voicecaps;
PDEBUG(DEBUG_H323, "H323 endpoint set endpoint type info *TBD*\n");
H323EndPoint::SetEndpointTypeInfo(info);
// protocols.SetTag(H225_SupportedProtocols::e_voice);
// (H225_VoiceCaps&)protocols = voicecaps;
// a_protocols.SetSize(1);
// a_protocols[0] = protocols;
// gateway.IncludeOptionalField(H225_GatewayInfo::e_protocol);
// gateway.m_protocol = a_protocols;
// info.m_gateway = gateway;
}

View File

@ -1,37 +0,0 @@
///////////////////////////////////////////////////////////////////////////////
// //
// PBX4Linux //
// //
//---------------------------------------------------------------------------//
// Copyright: Andreas Eversberg //
// //
// h323_ep endpoint header file //
// //
///////////////////////////////////////////////////////////////////////////////
#ifndef H323_EP_HEADER
#define H323_EP_HEADER
class H323_con;
class H323_ep : public H323EndPoint
{
public:
H323_ep(void);
~H323_ep();
H323Connection *CreateConnection(unsigned callReference);
void OnConnectionEstablished(H323Connection &connection, const PString &token);
BOOL OnAlerting(H323Connection &connection, const H323SignalPDU &alertingPDU, const PString &user);
void OnConnectionCleared(H323Connection &connection, const PString &token);
BOOL OpenAudioChannel(H323Connection &connection, BOOL isEncoding, unsigned bufferSize, H323AudioCodec &codec);
BOOL OpenVideoChannel(H323Connection &connection, BOOL isEncoding, H323VideoCodec &codec);
BOOL Init(void);
void SetEndpointTypeInfo (H225_EndpointType & info) const;
BOOL Call(char *token_string, char *caller, char *host);
private:
};
#endif // H323_EP_HEADER

View File

@ -1,137 +0,0 @@
/*****************************************************************************\
** **
** PBX4Linux **
** **
**---------------------------------------------------------------------------**
** Copyright: Andreas Eversberg **
** **
** parse h323 gateway config file **
** **
\*****************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "main.h"
/* parse h323_gateway.conf
*
* searches for the given ip and returns the extension or NULL if not found
*/
char *parse_h323gateway(char *ip, char *opt, int opt_size)
{
FILE *fp=NULL;
char filename[256];
char *p;
unsigned int line,i;
char buffer[256];
static char host_ip[32], extension[32], option[64];
int found = 0;
SPRINT(filename, "%s/h323_gateway.conf", INSTALL_DATA);
if (!(fp = fopen(filename, "r")))
{
PERROR("Cannot open h323 gateway map: \"%s\"\n", filename);
return(0);
}
line=0;
while((fgets(buffer, sizeof(buffer), fp)))
{
line++;
buffer[sizeof(buffer)-1] = '\0';
if (buffer[0]) buffer[strlen(buffer)-1] = '\0';
p = buffer;
while(*p <= 32) /* skip spaces */
{
if (*p == 0)
break;
p++;
}
if (*p==0 || *p=='#') /* ignore comments and empty line */
continue;
host_ip[0]=0;
extension[0]=0;
option[0]=0;
i=0; /* read host ip */
while(*p > 32)
{
if (i+1 >= sizeof(host_ip))
{
PERROR_RUNTIME("Error in %s (line %d): ip too long.\n",filename,line);
break;
}
host_ip[i+1] = '\0';
host_ip[i++] = *p++;
}
while(*p <= 32) /* skip spaces */
{
if (*p == 0)
break;
p++;
}
if (*p!=0 && *p!='#') /* extension */
{
i=0; /* read extension */
while(*p > 32)
{
if (i+1 >= sizeof(extension))
{
PERROR_RUNTIME("Error in %s (line %d): extension too long.\n",filename,line);
break;
}
extension[i+1] = '\0';
extension[i++] = *p++;
}
while(*p <= 32) /* skip spaces */
{
if (*p == 0)
break;
p++;
}
}
if (*p!=0 && *p!='#') /* option */
{
i=0; /* read option */
while(*p > 32)
{
if (i+1 >= sizeof(option))
{
PERROR_RUNTIME("Error in %s (line %d): option too long.\n",filename,line);
break;
}
option[i+1] = '\0';
option[i++] = *p++;
}
// ignoring more
}
if (!!strcasecmp(ip, host_ip))
continue;
if (extension[0] == '\0')
continue;
found = 1;
break; /* found entry */
}
if (fp) fclose(fp);
if (found)
{
UNCPY(opt, option, opt_size-1);
opt[opt_size-1] = '\0';
return(extension);
}
return(0);
}

View File

@ -1,14 +0,0 @@
/*****************************************************************************\
** **
** PBX4Linux **
** **
**---------------------------------------------------------------------------**
** Copyright: Andreas Eversberg **
** **
** h323gw header file **
** **
\*****************************************************************************/
char *parse_h323gateway(char *ip, char *opt, int opt_size);

View File

@ -5,7 +5,7 @@
**---------------------------------------------------------------------------**
** Copyright: Andreas Eversberg **
** **
** call functions **
** join functions **
** **
\*****************************************************************************/
@ -23,25 +23,25 @@
//#define __u32 unsigned long
//#include "linux/isdnif.h"
unsigned long call_serial = 1; /* must be 1, because 0== no call */
unsigned long join_serial = 1; /* must be 1, because 0== no join */
//CALL_STATES
//JOIN_STATES
class Call *call_first = NULL;
class Join *join_first = NULL;
/*
* find the call with call_id
* find the join with join_id
*/
class Call *find_call_id(unsigned long call_id)
class Join *find_join_id(unsigned long join_id)
{
class Call *call = call_first;
class Join *join = join_first;
while(call)
while(join)
{
//printf("comparing: '%s' with '%s'\n", name, call->c_name);
if (call->c_serial == call_id)
return(call);
call = call->next;
//printf("comparing: '%s' with '%s'\n", name, join->c_name);
if (join->c_serial == join_id)
return(join);
join = join->next;
}
return(NULL);
@ -49,37 +49,37 @@ class Call *find_call_id(unsigned long call_id)
/*
* constructor for a new call
* constructor for a new join
*/
Call::Call(void)
Join::Join(void)
{
class Call **callp;
class Join **joinp;
c_serial = call_serial++;
c_type = CALL_TYPE_NONE;
c_serial = join_serial++;
c_type = JOIN_TYPE_NONE;
/* attach to chain */
next = NULL;
callp = &call_first;
while(*callp)
callp = &((*callp)->next);
*callp = this;
joinp = &join_first;
while(*joinp)
joinp = &((*joinp)->next);
*joinp = this;
classuse++;
}
/*
* call descructor
* join descructor
*/
Call::~Call()
Join::~Join()
{
class Call *cl, **clp;
class Join *cl, **clp;
classuse--;
cl = call_first;
clp = &call_first;
cl = join_first;
clp = &join_first;
while(cl)
{
if (cl == this)
@ -88,46 +88,46 @@ Call::~Call()
cl = cl->next;
}
if (!cl)
FATAL("software error, call not in chain!\n");
FATAL("software error, join not in chain!\n");
*clp = cl->next; /* detach from chain */
}
/* epoint sends a message to a call
/* epoint sends a message to a join
*
*/
void Call::message_epoint(unsigned long epoint_id, int message_type, union parameter *param)
void Join::message_epoint(unsigned long epoint_id, int message_type, union parameter *param)
{
}
/* call process is called from the main loop
/* join process is called from the main loop
* it processes the current calling state.
* returns 0 if call nothing was done
* returns 0 if nothing was done
*/
int Call::handler(void)
int Join::handler(void)
{
return(0);
}
/* free all call structures */
void call_free(void)
/* free all join structures */
void join_free(void)
{
if (!call_first)
if (!join_first)
{
PDEBUG(DEBUG_CALL, "no more pending call(s), done!\n");
PDEBUG(DEBUG_JOIN, "no more pending join(s), done!\n");
return;
}
while(call_first)
while(join_first)
{
if (options.deb & DEBUG_CALL)
if (options.deb & DEBUG_JOIN)
{
PDEBUG(DEBUG_CALL, "freeing pending call\n");
PDEBUG(DEBUG_JOIN, "freeing pending join\n");
}
delete call_first;
delete join_first;
}
}

View File

@ -1,38 +1,38 @@
/*****************************************************************************\
** **
** PBX4Linux **
** Linux Call Router **
** **
**---------------------------------------------------------------------------**
** Copyright: Andreas Eversberg **
** **
** call header file **
** join header file **
** **
\*****************************************************************************/
enum { CALL_TYPE_NONE, CALL_TYPE_PBX, CALL_TYPE_ASTERISK};
enum { JOIN_TYPE_NONE, JOIN_TYPE_PBX, JOIN_TYPE_ASTERISK};
/* call
/* join
*
* abstraction for pbx calls and asterisk calls
*/
class Call
class Join
{
public:
Call();
virtual ~Call();
class Call *next; /* next node in list of calls */
Join();
virtual ~Join();
class Join *next; /* next node in list of joins */
virtual void message_epoint(unsigned long epoint_id, int message, union parameter *param);
virtual int handler(void);
unsigned long c_type; /* call type (pbx or asterisk) */
unsigned long c_serial; /* serial/unique number of call */
unsigned long c_type; /* join type (pbx or asterisk) */
unsigned long c_serial; /* serial/unique number of join */
};
void call_free(void);
void join_free(void);
extern class Call *call_first;
extern class Join *join_first;
class Call *find_call_id(unsigned long call_id);
class Join *find_join_id(unsigned long join_id);

View File

@ -1,11 +1,11 @@
/*****************************************************************************\
** **
** PBX4Linux **
** Linux Call Router **
** **
**---------------------------------------------------------------------------**
** Copyright: Andreas Eversberg **
** **
** call functions for channel driver **
** join functions for channel driver **
** **
\*****************************************************************************/
@ -25,41 +25,41 @@
/*
* constructor for a new call
* the call will have a relation to the calling endpoint
* constructor for a new join
* the join will have a relation to the calling endpoint
*/
CallAsterisk::CallAsterisk(unsigned long serial) : Call()
JoinAsterisk::JoinAsterisk(unsigned long serial) : Join()
{
PDEBUG(DEBUG_CALL, "Constructor(new call)");
PDEBUG(DEBUG_JOIN, "Constructor(new join)");
c_type = CALL_TYPE_ASTERISK;
c_type = JOIN_TYPE_ASTERISK;
c_epoint_id = serial;
if (c_epoint_id)
PDEBUG(DEBUG_CALL, "New call connected to endpoint id %lu\n", c_epoint_id);
PDEBUG(DEBUG_JOIN, "New join connected to endpoint id %lu\n", c_epoint_id);
}
/*
* call descructor
* join descructor
*/
CallAsterisk::~CallAsterisk()
JoinAsterisk::~JoinAsterisk()
{
}
/* call process is called from the main loop
/* join process is called from the main loop
* it processes the current calling state.
* returns 0 if call nothing was done
* returns 0 if join nothing was done
*/
int CallAsterisk::handler(void)
int JoinAsterisk::handler(void)
{
return(0);
}
void CallAsterisk::message_epoint(unsigned long epoint_id, int message_type, union parameter *param)
void JoinAsterisk::message_epoint(unsigned long epoint_id, int message_type, union parameter *param)
{
/* if endpoint has just been removed, but still a message in the que */
if (epoint_id != c_epoint_id)
@ -68,7 +68,7 @@ void CallAsterisk::message_epoint(unsigned long epoint_id, int message_type, uni
/* look for asterisk's interface */
if (admin_message_from_join(epoint_id, message_type, param)<0)
{
PERROR("No socket with asterisk found, this shall not happen. Closing socket shall cause release of all asterisk calls\n");
PERROR("No socket with asterisk found, this shall not happen. Closing socket shall cause release of all asterisk joins\n");
return;
}
@ -79,7 +79,7 @@ void CallAsterisk::message_epoint(unsigned long epoint_id, int message_type, uni
}
}
void CallAsterisk::message_asterisk(unsigned long callref, int message_type, union parameter *param)
void JoinAsterisk::message_asterisk(unsigned long ref, int message_type, union parameter *param)
{
struct message *message;
@ -88,13 +88,13 @@ void CallAsterisk::message_asterisk(unsigned long callref, int message_type, uni
{
class Endpoint *epoint;
if (!(epoint = new Endpoint(0, c_serial, callref)))
if (!(epoint = new Endpoint(0, c_serial, ref)))
FATAL("No memory for Endpoint instance\n");
if (!(epoint->ep_app = new DEFAULT_ENDPOINT_APP(epoint)))
FATAL("No memory for Endpoint Application instance\n");
}
message = message_create(c_serial, c_epoint_id, CALL_TO_EPOINT, message_type);
message = message_create(c_serial, c_epoint_id, JOIN_TO_EPOINT, message_type);
memcpy(&message->param, param, sizeof(message->param));
message_put(message);

View File

@ -1,21 +1,21 @@
/*****************************************************************************\
** **
** LCR **
** Linux Call Router **
** **
**---------------------------------------------------------------------------**
** Copyright: Andreas Eversberg **
** **
** call header file for Asterisk interface **
** join header file for Asterisk interface **
** **
\*****************************************************************************/
class CallAsterisk : public Call
class JoinAsterisk : public Join
{
public:
CallAsterisk(unsigned long serial);
~CallAsterisk();
JoinAsterisk(unsigned long serial);
~JoinAsterisk();
void message_epoint(unsigned long epoint_id, int message, union parameter *param);
void message_asterisk(unsigned long callref, int message_type, union parameter *param);
void message_asterisk(unsigned long ref, int message_type, union parameter *param);
int handler(void);
unsigned long c_epoint_id;

View File

@ -1,11 +1,11 @@
/*****************************************************************************\
** **
** PBX4Linux **
** Linux Call Router **
** **
**---------------------------------------------------------------------------**
** Copyright: Andreas Eversberg **
** **
** call functions **
** join functions **
** **
\*****************************************************************************/
@ -25,7 +25,7 @@
/* notify endpoint about state change (if any) */
static int notify_state_change(int call_id, int epoint_id, int old_state, int new_state)
static int notify_state_change(int join_id, int epoint_id, int old_state, int new_state)
{
int notify_off = 0, notify_on = 0;
struct message *message;
@ -102,16 +102,16 @@ static int notify_state_change(int call_id, int epoint_id, int old_state, int ne
break;
}
if (call_id && notify_off)
if (join_id && notify_off)
{
message = message_create(call_id, epoint_id, CALL_TO_EPOINT, MESSAGE_NOTIFY);
message = message_create(join_id, epoint_id, JOIN_TO_EPOINT, MESSAGE_NOTIFY);
message->param.notifyinfo.notify = notify_off;
message_put(message);
}
if (call_id && notify_on)
if (join_id && notify_on)
{
message = message_create(call_id, epoint_id, CALL_TO_EPOINT, MESSAGE_NOTIFY);
message = message_create(join_id, epoint_id, JOIN_TO_EPOINT, MESSAGE_NOTIFY);
message->param.notifyinfo.notify = notify_on;
message_put(message);
}
@ -120,30 +120,30 @@ static int notify_state_change(int call_id, int epoint_id, int old_state, int ne
}
/* debug function for call */
void callpbx_debug(class CallPBX *callpbx, char *function)
/* debug function for join */
void joinpbx_debug(class JoinPBX *joinpbx, char *function)
{
struct call_relation *relation;
struct join_relation *relation;
struct port_list *portlist;
class Endpoint *epoint;
class Port *port;
char buffer[512];
if (!(options.deb & DEBUG_CALL))
if (!(options.deb & DEBUG_JOIN))
return;
PDEBUG(DEBUG_CALL, "CALL(%d) start (called from %s)\n", callpbx->c_serial, function);
PDEBUG(DEBUG_JOIN, "join(%d) start (called from %s)\n", joinpbx->c_serial, function);
relation = callpbx->c_relation;
relation = joinpbx->c_relation;
if (!relation)
PDEBUG(DEBUG_CALL, "call has no relations\n");
PDEBUG(DEBUG_JOIN, "join has no relations\n");
while(relation)
{
epoint = find_epoint_id(relation->epoint_id);
if (!epoint)
{
PDEBUG(DEBUG_CALL, "warning: relations epoint id=%ld doesn't exists!\n", relation->epoint_id);
PDEBUG(DEBUG_JOIN, "warning: relations epoint id=%ld doesn't exists!\n", relation->epoint_id);
relation = relation->next;
continue;
}
@ -160,8 +160,8 @@ void callpbx_debug(class CallPBX *callpbx, char *function)
UPRINT(strchr(buffer,0), "<port %ld doesn't exist>,", portlist->port_id);
portlist = portlist->next;
}
// UPRINT(strchr(buffer,0), " endpoint=%d on=%s hold=%s", epoint->ep_serial, (epoint->ep_call_id==callpbx->c_serial)?"yes":"no", (epoint->get_hold_id()==callpbx->c_serial)?"yes":"no");
UPRINT(strchr(buffer,0), " endpoint=%d on=%s", epoint->ep_serial, (epoint->ep_call_id==callpbx->c_serial)?"yes":"no");
// UPRINT(strchr(buffer,0), " endpoint=%d on=%s hold=%s", epoint->ep_serial, (epoint->ep_join_id==joinpbx->c_serial)?"yes":"no", (epoint->get_hold_id()==joinpbx->c_serial)?"yes":"no");
UPRINT(strchr(buffer,0), " endpoint=%d on=%s", epoint->ep_serial, (epoint->ep_join_id==joinpbx->c_serial)?"yes":"no");
switch(relation->type)
{
case RELATION_TYPE_CALLING:
@ -225,29 +225,29 @@ void callpbx_debug(class CallPBX *callpbx, char *function)
UPRINT(strchr(buffer,0), " rx_state=unknown");
break;
}
PDEBUG(DEBUG_CALL, "%s\n", buffer);
PDEBUG(DEBUG_JOIN, "%s\n", buffer);
relation = relation->next;
}
PDEBUG(DEBUG_CALL, "end\n");
PDEBUG(DEBUG_JOIN, "end\n");
}
/*
* constructor for a new call
* the call will have a relation to the calling endpoint
* constructor for a new join
* the join will have a relation to the calling endpoint
*/
CallPBX::CallPBX(class Endpoint *epoint) : Call()
JoinPBX::JoinPBX(class Endpoint *epoint) : Join()
{
struct call_relation *relation;
struct join_relation *relation;
// char filename[256];
if (!epoint)
FATAL("epoint is NULL.\n");
PDEBUG(DEBUG_CALL, "creating new call and connecting it to the endpoint.\n");
PDEBUG(DEBUG_JOIN, "creating new join and connecting it to the endpoint.\n");
c_type = CALL_TYPE_PBX;
c_type = JOIN_TYPE_PBX;
c_caller[0] = '\0';
c_caller_id[0] = '\0';
c_dialed[0] = '\0';
@ -259,44 +259,44 @@ CallPBX::CallPBX(class Endpoint *epoint) : Call()
c_multilocation = LOCATION_PRIVATE_LOCAL;
/* initialize a relation only to the calling interface */
relation = c_relation = (struct call_relation *)MALLOC(sizeof(struct call_relation));
relation = c_relation = (struct join_relation *)MALLOC(sizeof(struct join_relation));
cmemuse++;
relation->type = RELATION_TYPE_CALLING;
relation->channel_state = CHANNEL_STATE_HOLD; /* audio is assumed on a new call */
relation->tx_state = NOTIFY_STATE_ACTIVE; /* new calls always assumed to be active */
relation->rx_state = NOTIFY_STATE_ACTIVE; /* new calls always assumed to be active */
relation->channel_state = CHANNEL_STATE_HOLD; /* audio is assumed on a new join */
relation->tx_state = NOTIFY_STATE_ACTIVE; /* new joins always assumed to be active */
relation->rx_state = NOTIFY_STATE_ACTIVE; /* new joins always assumed to be active */
relation->epoint_id = epoint->ep_serial;
if (options.deb & DEBUG_CALL)
callpbx_debug(this, "CallPBX::Constructor(new call)");
if (options.deb & DEBUG_JOIN)
joinpbx_debug(this, "JoinPBX::Constructor(new join)");
}
/*
* call descructor
* join descructor
*/
CallPBX::~CallPBX()
JoinPBX::~JoinPBX()
{
struct call_relation *relation, *rtemp;
struct join_relation *relation, *rtemp;
relation = c_relation;
while(relation)
{
rtemp = relation->next;
FREE(relation, sizeof(struct call_relation));
FREE(relation, sizeof(struct join_relation));
cmemuse--;
relation = rtemp;
}
}
/* bridge sets the audio flow of all bchannels assiociated to 'this' call
/* bridge sets the audio flow of all bchannels assiociated to 'this' join
* also it changes and notifies active/hold/conference states
*/
void CallPBX::bridge(void)
void JoinPBX::bridge(void)
{
struct call_relation *relation;
struct join_relation *relation;
struct message *message;
int numconnect = 0, relations = 0;
class Endpoint *epoint;
@ -325,7 +325,7 @@ void CallPBX::bridge(void)
portlist = epoint->ep_portlist;
if (!portlist)
{
PDEBUG(DEBUG_CALL, "CALL%d ignoring relation without port object.\n", c_serial);
PDEBUG(DEBUG_JOIN, "join%d ignoring relation without port object.\n", c_serial);
//#warning testing: keep on hold until single audio stream available
relation->channel_state = CHANNEL_STATE_HOLD;
relation = relation->next;
@ -333,7 +333,7 @@ void CallPBX::bridge(void)
}
if (portlist->next)
{
PDEBUG(DEBUG_CALL, "CALL%d ignoring relation with ep%d due to port_list.\n", c_serial, epoint->ep_serial);
PDEBUG(DEBUG_JOIN, "join%d ignoring relation with ep%d due to port_list.\n", c_serial, epoint->ep_serial);
//#warning testing: keep on hold until single audio stream available
relation->channel_state = CHANNEL_STATE_HOLD;
relation = relation->next;
@ -342,16 +342,16 @@ void CallPBX::bridge(void)
port = find_port_id(portlist->port_id);
if (!port)
{
PDEBUG(DEBUG_CALL, "CALL%d ignoring relation without existing port object.\n", c_serial);
PDEBUG(DEBUG_JOIN, "join%d ignoring relation without existing port object.\n", c_serial);
relation = relation->next;
continue;
}
if ((port->p_type&PORT_CLASS_MASK)!=PORT_CLASS_mISDN)
{
PDEBUG(DEBUG_CALL, "CALL%d ignoring relation ep%d because it's port is not mISDN.\n", c_serial, epoint->ep_serial);
PDEBUG(DEBUG_JOIN, "join%d ignoring relation ep%d because it's port is not mISDN.\n", c_serial, epoint->ep_serial);
if (allmISDN)
{
PDEBUG(DEBUG_CALL, "CALL%d not all endpoints are mISDN.\n", c_serial);
PDEBUG(DEBUG_JOIN, "join%d not all endpoints are mISDN.\n", c_serial);
allmISDN = 0;
}
relation = relation->next;
@ -361,7 +361,7 @@ void CallPBX::bridge(void)
relation = relation->next;
}
PDEBUG(DEBUG_CALL, "CALL%d members=%d %s\n", c_serial, relations, (allmISDN)?"(all are mISDN-members)":"(not all are mISDN-members)");
PDEBUG(DEBUG_JOIN, "join%d members=%d %s\n", c_serial, relations, (allmISDN)?"(all are mISDN-members)":"(not all are mISDN-members)");
/* we notify all relations about rxdata. */
relation = c_relation;
while(relation)
@ -379,17 +379,17 @@ void CallPBX::bridge(void)
&& relations>1 // no conf with one member
&& allmISDN) // no conf if any member is not mISDN
{
message = message_create(c_serial, relation->epoint_id, CALL_TO_EPOINT, MESSAGE_mISDNSIGNAL);
message = message_create(c_serial, relation->epoint_id, JOIN_TO_EPOINT, MESSAGE_mISDNSIGNAL);
message->param.mISDNsignal.message = mISDNSIGNAL_CONF;
message->param.mISDNsignal.conf = c_serial<<16 | c_pid;
PDEBUG(DEBUG_CALL, "CALL%d EP%d +on+ id: 0x%08x\n", c_serial, relation->epoint_id, message->param.mISDNsignal.conf);
PDEBUG(DEBUG_JOIN, "join%d EP%d +on+ id: 0x%08x\n", c_serial, relation->epoint_id, message->param.mISDNsignal.conf);
message_put(message);
} else
{
message = message_create(c_serial, relation->epoint_id, CALL_TO_EPOINT, MESSAGE_mISDNSIGNAL);
message = message_create(c_serial, relation->epoint_id, JOIN_TO_EPOINT, MESSAGE_mISDNSIGNAL);
message->param.mISDNsignal.message = mISDNSIGNAL_CONF;
message->param.mISDNsignal.conf = 0;
PDEBUG(DEBUG_CALL, "CALL%d EP%d +off+ id: 0x%08x\n", c_serial, relation->epoint_id, message->param.mISDNsignal.conf);
PDEBUG(DEBUG_JOIN, "join%d EP%d +off+ id: 0x%08x\n", c_serial, relation->epoint_id, message->param.mISDNsignal.conf);
message_put(message);
}
@ -399,10 +399,10 @@ void CallPBX::bridge(void)
* - 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_CALLDATA;
message->param.mISDNsignal.calldata = (relations==2 && !allmISDN);
PDEBUG(DEBUG_CALL, "CALL%d EP%d set calldata=%d\n", c_serial, relation->epoint_id, message->param.mISDNsignal.calldata);
message = message_create(c_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", c_serial, relation->epoint_id, message->param.mISDNsignal.joindata);
message_put(message);
relation = relation->next;
@ -411,15 +411,15 @@ void CallPBX::bridge(void)
/* two people just exchange their states */
if (relations==2 && !c_partyline)
{
PDEBUG(DEBUG_CALL, "CALL%d 2 relations / no partyline\n", c_serial);
PDEBUG(DEBUG_JOIN, "join%d 2 relations / no partyline\n", c_serial);
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
/* one member in a call, so we put her on hold */
/* one member in a join, so we put her on hold */
if (relations==1 || numconnect==1)
{
PDEBUG(DEBUG_CALL, "CALL%d 1 member or only 1 connected, put on hold\n");
PDEBUG(DEBUG_JOIN, "join%d 1 member or only 1 connected, put on hold\n");
relation = c_relation;
while(relation)
{
@ -432,7 +432,7 @@ void CallPBX::bridge(void)
} else
/* if conference/partyline or (more than two members and more than one is connected), so we set conference state */
{
PDEBUG(DEBUG_CALL, "CALL%d %d members, %d connected, signal conference\n", relations, numconnect);
PDEBUG(DEBUG_JOIN, "join%d %d members, %d connected, signal conference\n", relations, numconnect);
relation = c_relation;
while(relation)
{
@ -448,9 +448,9 @@ void CallPBX::bridge(void)
/*
* bridging is only possible with two connected endpoints
*/
void CallPBX::bridge_data(unsigned long epoint_from, struct call_relation *relation_from, union parameter *param)
void JoinPBX::bridge_data(unsigned long epoint_from, struct join_relation *relation_from, union parameter *param)
{
struct call_relation *relation_to;
struct join_relation *relation_to;
/* if we are alone */
if (!c_relation->next)
@ -480,20 +480,20 @@ void CallPBX::bridge_data(unsigned long epoint_from, struct call_relation *relat
* will be delivered to the port
*/
//printf("from %d, to %d\n", relation_from->epoint_id, relation_to->epoint_id);
message_forward(c_serial, relation_to->epoint_id, CALL_TO_EPOINT, param);
message_forward(c_serial, relation_to->epoint_id, JOIN_TO_EPOINT, param);
}
/* release call from endpoint
* if the call has two relations, all relations are freed and the call will be
/* release join from endpoint
* if the join has two relations, all relations are freed and the join will be
* destroyed
* on outgoing relations, the cause is collected, if not connected
* returns if call has been destroyed
* returns if join has been destroyed
*/
int CallPBX::release(struct call_relation *relation, int location, int cause)
int JoinPBX::release(struct join_relation *relation, int location, int cause)
{
struct call_relation *reltemp, **relationpointer;
struct join_relation *reltemp, **relationpointer;
struct message *message;
class Call *call;
class Join *join;
int destroy = 0;
/* remove from bridge */
@ -501,7 +501,7 @@ int CallPBX::release(struct call_relation *relation, int location, int cause)
{
relation->channel_state = CHANNEL_STATE_HOLD;
c_updatebridge = 1; /* update bridge flag */
// note: if call is not released, bridge must be updated
// note: if join is not released, bridge must be updated
}
/* detach given interface */
@ -518,73 +518,73 @@ int CallPBX::release(struct call_relation *relation, int location, int cause)
if (!reltemp)
FATAL("relation not in list of our relations. this must not happen.\n");
*relationpointer = reltemp->next;
FREE(reltemp, sizeof(struct call_relation));
FREE(reltemp, sizeof(struct join_relation));
cmemuse--;
relation = reltemp = NULL; // just in case of reuse fault;
/* if no more relation */
if (!c_relation)
{
PDEBUG(DEBUG_CALL, "call is completely removed.\n");
/* there is no more endpoint related to the call */
PDEBUG(DEBUG_JOIN, "join is completely removed.\n");
/* there is no more endpoint related to the join */
destroy = 1;
delete this;
// end of call object!
PDEBUG(DEBUG_CALL, "call completely removed!\n");
// end of join object!
PDEBUG(DEBUG_JOIN, "join completely removed!\n");
} else
/* if call is a party line */
/* if join is a party line */
if (c_partyline)
{
PDEBUG(DEBUG_CALL, "call is a conference room, so we keep it alive until the last party left.\n");
PDEBUG(DEBUG_JOIN, "join is a conference room, so we keep it alive until the last party left.\n");
} else
/* if only one relation left */
if (!c_relation->next)
{
PDEBUG(DEBUG_CALL, "call has one relation left, so we send it a release with the given cause %d.\n", cause);
message = message_create(c_serial, c_relation->epoint_id, CALL_TO_EPOINT, MESSAGE_RELEASE);
PDEBUG(DEBUG_JOIN, "join has one relation left, so we send it a release with the given cause %d.\n", cause);
message = message_create(c_serial, c_relation->epoint_id, JOIN_TO_EPOINT, MESSAGE_RELEASE);
message->param.disconnectinfo.cause = cause;
message->param.disconnectinfo.location = location;
message_put(message);
destroy = 1;
delete this;
// end of call object!
PDEBUG(DEBUG_CALL, "call completely removed!\n");
// end of join object!
PDEBUG(DEBUG_JOIN, "join completely removed!\n");
}
call = call_first;
while(call)
join = join_first;
while(join)
{
if (options.deb & DEBUG_CALL && call->c_type==CALL_TYPE_PBX)
callpbx_debug((class CallPBX *)call, "call_release{all calls left}");
call = call->next;
if (options.deb & DEBUG_JOIN && join->c_type==JOIN_TYPE_PBX)
joinpbx_debug((class JoinPBX *)join, "join_release{all joins left}");
join = join->next;
}
PDEBUG(DEBUG_CALL, "call_release(): ended.\n");
PDEBUG(DEBUG_JOIN, "join_release(): ended.\n");
return(destroy);
}
/* count number of relations in a call
/* count number of relations in a join
*/
int callpbx_countrelations(unsigned long call_id)
int joinpbx_countrelations(unsigned long join_id)
{
struct call_relation *relation;
struct join_relation *relation;
int i;
class Call *call;
class CallPBX *callpbx;
class Join *join;
class JoinPBX *joinpbx;
call = find_call_id(call_id);
join = find_join_id(join_id);
if (!call)
if (!join)
return(0);
if (call->c_type != CALL_TYPE_ASTERISK)
if (join->c_type != JOIN_TYPE_ASTERISK)
return(2);
if (call->c_type != CALL_TYPE_PBX)
if (join->c_type != JOIN_TYPE_PBX)
return(0);
callpbx = (class CallPBX *)call;
joinpbx = (class JoinPBX *)join;
i = 0;
relation = callpbx->c_relation;
relation = joinpbx->c_relation;
while(relation)
{
i++;
@ -594,9 +594,9 @@ int callpbx_countrelations(unsigned long call_id)
return(i);
}
void CallPBX::remove_relation(struct call_relation *relation)
void JoinPBX::remove_relation(struct join_relation *relation)
{
struct call_relation *temp, **tempp;
struct join_relation *temp, **tempp;
if (!relation)
return;
@ -612,46 +612,46 @@ void CallPBX::remove_relation(struct call_relation *relation)
}
if (!temp)
{
PERROR("relation not in call.\n");
PERROR("relation not in join.\n");
return;
}
PDEBUG(DEBUG_CALL, "removing relation.\n");
PDEBUG(DEBUG_JOIN, "removing relation.\n");
*tempp = relation->next;
FREE(temp, sizeof(struct call_relation));
FREE(temp, sizeof(struct join_relation));
cmemuse--;
}
struct call_relation *CallPBX::add_relation(void)
struct join_relation *JoinPBX::add_relation(void)
{
struct call_relation *relation;
struct join_relation *relation;
if (!c_relation)
{
PERROR("there is no first relation to this call\n");
PERROR("there is no first relation to this join\n");
return(NULL);
}
relation = c_relation;
while(relation->next)
relation = relation->next;
relation->next = (struct call_relation *)MALLOC(sizeof(struct call_relation));
relation->next = (struct join_relation *)MALLOC(sizeof(struct join_relation));
cmemuse++;
/* the record pointer is set at the first time the data is received for the relation */
// if (options.deb & DEBUG_CALL)
// callpbx_debug(call, "add_relation");
// if (options.deb & DEBUG_JOIN)
// joinpbx_debug(join, "add_relation");
return(relation->next);
}
/* epoint sends a message to a call
/* epoint sends a message to a join
*
*/
void CallPBX::message_epoint(unsigned long epoint_id, int message_type, union parameter *param)
void JoinPBX::message_epoint(unsigned long epoint_id, int message_type, union parameter *param)
{
class Call *cl;
struct call_relation *relation, *reltemp;
class Join *cl;
struct join_relation *relation, *reltemp;
int num;
int new_state;
struct message *message;
@ -664,20 +664,20 @@ void CallPBX::message_epoint(unsigned long epoint_id, int message_type, union pa
return;
}
// if (options.deb & DEBUG_CALL)
// if (options.deb & DEBUG_JOIN)
// {
// PDEBUG(DEBUG_CALL, "message %d received from ep%d.\n", message, epoint->ep_serial);
// callpbx_debug(call,"Call::message_epoint");
// PDEBUG(DEBUG_JOIN, "message %d received from ep%d.\n", message, epoint->ep_serial);
// joinpbx_debug(join,"Join::message_epoint");
// }
if (options.deb & DEBUG_CALL)
if (options.deb & DEBUG_JOIN)
{
if (message_type != MESSAGE_DATA)
{
cl = call_first;
cl = join_first;
while(cl)
{
if (cl->c_type == CALL_TYPE_PBX)
callpbx_debug((class CallPBX *)cl, "Call::message_epoint{all calls before processing}");
if (cl->c_type == JOIN_TYPE_PBX)
joinpbx_debug((class JoinPBX *)cl, "Join::message_epoint{all joins before processing}");
cl = cl->next;
}
}
@ -693,7 +693,7 @@ void CallPBX::message_epoint(unsigned long epoint_id, int message_type, union pa
}
if (!relation)
{
PDEBUG(DEBUG_CALL, "no relation back to the endpoint found, ignoring (call=%d, endpoint=%d)\n", c_serial, epoint_id);
PDEBUG(DEBUG_JOIN, "no relation back to the endpoint found, ignoring (join=%d, endpoint=%d)\n", c_serial, epoint_id);
return;
}
@ -701,13 +701,13 @@ void CallPBX::message_epoint(unsigned long epoint_id, int message_type, union pa
{
/* process channel message */
case MESSAGE_CHANNEL:
PDEBUG(DEBUG_CALL, "call received channel message: %d.\n", param->channel);
PDEBUG(DEBUG_JOIN, "join received channel message: %d.\n", param->channel);
if (relation->channel_state != param->channel)
{
relation->channel_state = param->channel;
c_updatebridge = 1; /* update bridge flag */
if (options.deb & DEBUG_CALL)
callpbx_debug(this, "Call::message_epoint{after setting new channel state}");
if (options.deb & DEBUG_JOIN)
joinpbx_debug(this, "Join::message_epoint{after setting new channel state}");
}
return;
@ -726,8 +726,8 @@ void CallPBX::message_epoint(unsigned long epoint_id, int message_type, union pa
{
relation->rx_state = new_state;
c_updatebridge = 1;
if (options.deb & DEBUG_CALL)
callpbx_debug(this, "Call::message_epoint{after setting new rx state}");
if (options.deb & DEBUG_JOIN)
joinpbx_debug(this, "Join::message_epoint{after setting new rx state}");
}
break;
@ -738,7 +738,7 @@ void CallPBX::message_epoint(unsigned long epoint_id, int message_type, union pa
{
if (reltemp->epoint_id!=epoint_id && reltemp->epoint_id)
{
message = message_create(c_serial, reltemp->epoint_id, CALL_TO_EPOINT, MESSAGE_NOTIFY);
message = message_create(c_serial, reltemp->epoint_id, JOIN_TO_EPOINT, MESSAGE_NOTIFY);
memcpy(&message->param, param, sizeof(union parameter));
message_put(message);
}
@ -766,7 +766,7 @@ void CallPBX::message_epoint(unsigned long epoint_id, int message_type, union pa
if (relation->type == RELATION_TYPE_SETUP)
{
if (release(relation, LOCATION_PRIVATE_LOCAL, CAUSE_NONSELECTED))
return; // must return, because call IS destroyed
return; // must return, because join IS destroyed
goto release_again;
}
relation = relation->next;
@ -785,15 +785,15 @@ void CallPBX::message_epoint(unsigned long epoint_id, int message_type, union pa
/* send current cause */
release(relation, param->disconnectinfo.location, param->disconnectinfo.cause);
}
return; // must return, because call may be destroyed
return; // must return, because join may be destroyed
}
/* process party line */
if (message_type == MESSAGE_SETUP) if (param->setup.partyline)
{
PDEBUG(DEBUG_CALL, "respsone with connect in partyline mode.\n");
PDEBUG(DEBUG_JOIN, "respsone with connect in partyline mode.\n");
c_partyline = param->setup.partyline;
message = message_create(c_serial, epoint_id, CALL_TO_EPOINT, MESSAGE_CONNECT);
message = message_create(c_serial, epoint_id, JOIN_TO_EPOINT, MESSAGE_CONNECT);
message->param.setup.partyline = c_partyline;
message_put(message);
c_updatebridge = 1; /* update bridge flag */
@ -802,8 +802,8 @@ void CallPBX::message_epoint(unsigned long epoint_id, int message_type, union pa
{
if (message_type == MESSAGE_DISCONNECT)
{
PDEBUG(DEBUG_CALL, "releasing after receiving disconnect, because call in partyline mode.\n");
message = message_create(c_serial, epoint_id, CALL_TO_EPOINT, MESSAGE_RELEASE);
PDEBUG(DEBUG_JOIN, "releasing after receiving disconnect, because join in partyline mode.\n");
message = message_create(c_serial, epoint_id, JOIN_TO_EPOINT, MESSAGE_RELEASE);
message->param.disconnectinfo.cause = CAUSE_NORMAL;
message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
message_put(message);
@ -812,17 +812,17 @@ void CallPBX::message_epoint(unsigned long epoint_id, int message_type, union pa
}
if (c_partyline)
{
PDEBUG(DEBUG_CALL, "ignoring message, because call in partyline mode.\n");
PDEBUG(DEBUG_JOIN, "ignoring message, because join in partyline mode.\n");
return;
}
/* count relations */
num=callpbx_countrelations(c_serial);
num=joinpbx_countrelations(c_serial);
/* check number of relations */
if (num > 2)
{
PDEBUG(DEBUG_CALL, "call has more than two relations so there is no need to send a message.\n");
PDEBUG(DEBUG_JOIN, "join has more than two relations so there is no need to send a message.\n");
return;
}
@ -845,35 +845,35 @@ void CallPBX::message_epoint(unsigned long epoint_id, int message_type, union pa
while((number = strsep(&numbers, ",")))
{
if (out_setup(epoint_id, message_type, param, number))
return; // call destroyed
return; // join destroyed
}
break;
}
if (out_setup(epoint_id, message_type, param, NULL))
return; // call destroyed
return; // join destroyed
break;
default:
PDEBUG(DEBUG_CALL, "no need to send a message because there is no other endpoint than the calling one.\n");
PDEBUG(DEBUG_JOIN, "no need to send a message because there is no other endpoint than the calling one.\n");
}
} else
{
PDEBUG(DEBUG_CALL, "sending message ep%ld -> ep%ld.\n", epoint_id, relation->epoint_id);
message = message_create(c_serial, relation->epoint_id, CALL_TO_EPOINT, message_type);
PDEBUG(DEBUG_JOIN, "sending message ep%ld -> ep%ld.\n", epoint_id, relation->epoint_id);
message = message_create(c_serial, relation->epoint_id, JOIN_TO_EPOINT, message_type);
memcpy(&message->param, param, sizeof(union parameter));
message_put(message);
PDEBUG(DEBUG_CALL, "message sent.\n");
PDEBUG(DEBUG_JOIN, "message sent.\n");
}
}
/* call process is called from the main loop
/* join process is called from the main loop
* it processes the current calling state.
* returns 0 if call nothing was done
* returns 0 if join nothing was done
*/
int CallPBX::handler(void)
int JoinPBX::handler(void)
{
// struct call_relation *relation;
// struct join_relation *relation;
// char dialing[32][32];
// int port[32];
// int found;
@ -928,22 +928,22 @@ int track_notify(int oldstate, int notify)
* setup to exactly one endpoint
* if it fails, the calling endpoint is released.
* if other outgoing endpoints already exists, they are release as well.
* note: if this functions fails, it will destroy its own call object!
* note: if this functions fails, it will destroy its own join object!
*/
int CallPBX::out_setup(unsigned long epoint_id, int message_type, union parameter *param, char *newnumber)
int JoinPBX::out_setup(unsigned long epoint_id, int message_type, union parameter *param, char *newnumber)
{
struct call_relation *relation;
struct join_relation *relation;
struct message *message;
class Endpoint *epoint;
PDEBUG(DEBUG_CALL, "no endpoint found, so we will create an endpoint and send the setup message we have.\n");
PDEBUG(DEBUG_JOIN, "no endpoint found, so we will create an endpoint and send the setup message we have.\n");
/* create a new relation */
if (!(relation=add_relation()))
FATAL("No memory for relation.\n");
relation->type = RELATION_TYPE_SETUP;
relation->channel_state = CHANNEL_STATE_HOLD; /* audio is assumed on a new call */
relation->tx_state = NOTIFY_STATE_ACTIVE; /* new calls always assumed to be active */
relation->rx_state = NOTIFY_STATE_ACTIVE; /* new calls always assumed to be active */
relation->channel_state = CHANNEL_STATE_HOLD; /* audio is assumed on a new join */
relation->tx_state = NOTIFY_STATE_ACTIVE; /* new joins always assumed to be active */
relation->rx_state = NOTIFY_STATE_ACTIVE; /* new joins always assumed to be active */
/* create a new endpoint */
epoint = new Endpoint(0, c_serial, 0);
if (!epoint)
@ -952,14 +952,14 @@ int CallPBX::out_setup(unsigned long epoint_id, int message_type, union paramete
FATAL("No memory for Endpoint Application instance\n");
relation->epoint_id = epoint->ep_serial;
/* send setup message to new endpoint */
//printf("JOLLY DEBUG: %d\n",call_countrelations(c_serial));
//i if (options.deb & DEBUG_CALL)
// callpbx_debug(call, "Call::message_epoint");
message = message_create(c_serial, relation->epoint_id, CALL_TO_EPOINT, message_type);
//printf("JOLLY DEBUG: %d\n",join_countrelations(c_serial));
//i if (options.deb & DEBUG_JOIN)
// joinpbx_debug(join, "Join::message_epoint");
message = message_create(c_serial, relation->epoint_id, JOIN_TO_EPOINT, message_type);
memcpy(&message->param, param, sizeof(union parameter));
if (newnumber)
SCPY(message->param.setup.dialinginfo.id, newnumber);
PDEBUG(DEBUG_CALL, "setup message sent to ep %d with number='%s'.\n", relation->epoint_id, message->param.setup.dialinginfo.id);
PDEBUG(DEBUG_JOIN, "setup message sent to ep %d with number='%s'.\n", relation->epoint_id, message->param.setup.dialinginfo.id);
message_put(message);
return(0);
}

View File

@ -1,34 +1,34 @@
/*****************************************************************************\
** **
** PBX4Linux **
** Linux Call Router **
** **
**---------------------------------------------------------------------------**
** Copyright: Andreas Eversberg **
** **
** call header file for pbx calls **
** join header file for pbx joins **
** **
\*****************************************************************************/
/* call
/* join
*
* calls connect interfaces together
* calls are linked in a chain
* interfaces can have 0, 1 or more references to a call
* the call can have many references to interfaces
* calls receive and send messages
* joins connect interfaces together
* joins are linked in a chain
* interfaces can have 0, 1 or more references to a join
* the join can have many references to interfaces
* joins receive and send messages
*/
#define RECORD_BUFFER_SIZE 16000
enum { /* relation types */
RELATION_TYPE_CALLING, /* initiator of a call */
RELATION_TYPE_CALLING, /* initiator of a join */
RELATION_TYPE_SETUP, /* interface which is to be set up */
RELATION_TYPE_CONNECT, /* interface is connected */
};
enum { /* relation audio state */
CHANNEL_STATE_CONNECT, /* endpoint is connected to the call voice transmission in both dirs */
CHANNEL_STATE_CONNECT, /* endpoint is connected to the join voice transmission in both dirs */
CHANNEL_STATE_HOLD, /* endpoint is on hold state, no audio */
};
@ -40,23 +40,23 @@ enum { /* states that results from last notification */
};
struct call_relation { /* relation to an interface */
struct call_relation *next; /* next node */
struct join_relation { /* relation to an interface */
struct join_relation *next; /* next node */
int type; /* type of relation */
unsigned long epoint_id; /* interface to link call to */
unsigned long epoint_id; /* interface to link join to */
int channel_state; /* if audio is available */
int rx_state; /* current state of what we received from endpoint */
int tx_state; /* current state of what we sent to endpoint */
};
class CallPBX : public Call
class JoinPBX : public Join
{
public:
CallPBX(class Endpoint *epoint);
~CallPBX();
JoinPBX(class Endpoint *epoint);
~JoinPBX();
void message_epoint(unsigned long epoint_id, int message, union parameter *param);
int handler(void);
int release(struct call_relation *relation, int location, int cause);
int release(struct join_relation *relation, int location, int cause);
char c_caller[32]; /* caller number */
char c_caller_id[32]; /* caller id to signal */
@ -64,20 +64,20 @@ class CallPBX : public Call
char c_todial[32]; /* overlap dialing (part not signalled yet) */
int c_multicause, c_multilocation;
int c_pid; /* pid of call to generate bridge id */
int c_pid; /* pid of join to generate bridge id */
int c_updatebridge; /* bridge must be updated */
struct call_relation *c_relation; /* list of endpoints that are related to the call */
struct join_relation *c_relation; /* list of endpoints that are related to the join */
int c_partyline; /* if set, call is conference room */
int c_partyline; /* if set, join is conference room */
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);
void bridge_data(unsigned long 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 long epoint_id, int message, union parameter *param, char *newnumber);
};
void callpbx_debug(class CallPBX *callpbx, char *function);
int callpbx_countrelations(unsigned long call_id);
void joinpbx_debug(class JoinPBX *joinpbx, char *function);
int joinpbx_countrelations(unsigned long join_id);
int track_notify(int oldstate, int notify);

View File

@ -62,7 +62,7 @@ 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_calldata = 0;
p_m_joindata = 0;
p_m_dtmf = !mISDNport->ifport->nodtmf;
p_m_timeout = 0;
p_m_timer = 0;
@ -910,8 +910,8 @@ int PmISDN::handler(void)
message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_TIMEOUT);
message->param.state = p_state;
message_put(message);
return(1);
}
return(1);
}
return(0); /* nothing done */
@ -998,7 +998,7 @@ void PmISDN::bchannel_receive(iframe_t *frm)
/* calls will not process any audio data unless
* the call is connected OR interface features audio during call setup.
*/
//printf("%d -> %d prim=%x calldata=%d tones=%d\n", p_serial, ACTIVE_EPOINT(p_epointlist), frm->prim, p_m_calldata, p_m_mISDNport->earlyb);
//printf("%d -> %d prim=%x joindata=%d tones=%d\n", p_serial, ACTIVE_EPOINT(p_epointlist), frm->prim, p_m_joindata, p_m_mISDNport->earlyb);
#ifndef DEBUG_COREBRIDGE
if (p_state!=PORT_STATE_CONNECT
&& !p_m_mISDNport->earlyb)
@ -1031,7 +1031,7 @@ void PmISDN::bchannel_receive(iframe_t *frm)
p = (unsigned char *)&frm->data.p;
/* send data to epoint */
if (p_m_calldata && ACTIVE_EPOINT(p_epointlist)) /* only if we have an epoint object */
if (p_m_joindata && ACTIVE_EPOINT(p_epointlist)) /* only if we have an epoint object */
{
length_temp = frm->len;
data_temp = p;
@ -1222,13 +1222,13 @@ 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)
case mISDNSIGNAL_JOINDATA:
if (p_m_joindata != param->mISDNsignal.joindata)
{
p_m_calldata = param->mISDNsignal.calldata;
PDEBUG(DEBUG_BCHANNEL, "we change to calldata=%d.\n", p_m_calldata);
p_m_joindata = param->mISDNsignal.joindata;
PDEBUG(DEBUG_BCHANNEL, "we change to joindata=%d.\n", p_m_joindata);
} else
PDEBUG(DEBUG_BCHANNEL, "we already have calldata=%d.\n", p_m_calldata);
PDEBUG(DEBUG_BCHANNEL, "we already have joindata=%d.\n", p_m_joindata);
break;
case mISDNSIGNAL_DELAY:
@ -1370,7 +1370,7 @@ int mISDN_handler(void)
if (isdnport)
{
/* call bridges in user space OR crypto OR recording */
if (isdnport->p_m_calldata || isdnport->p_m_crypt_msg_loops || isdnport->p_m_crypt_listen || isdnport->p_record)
if (isdnport->p_m_joindata || isdnport->p_m_crypt_msg_loops || isdnport->p_m_crypt_listen || isdnport->p_record)
{
/* rx IS required */
if (isdnport->p_m_rxoff)

View File

@ -1,6 +1,6 @@
/*****************************************************************************\
** **
** PBX4Linux **
** Linux Call Router **
** **
**---------------------------------------------------------------------------**
** Copyright: Andreas Eversberg **
@ -118,7 +118,7 @@ class PmISDN : public Port
// 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_calldata; /* the call requires data due to no briging capability */
int p_m_joindata; /* the call requires data due to no briging capability */
int p_m_load; /* current data in dsp tx buffer */
unsigned long p_m_last_tv_sec; /* time stamp of last handler call, (to sync audio data */

75
main.c
View File

@ -185,7 +185,7 @@ int main(int argc, char *argv[])
struct message *message;
class Port *port;
class Endpoint *epoint;
class Call *call;
class Join *join;
int i;
int all_idle;
char prefix_string[64];
@ -195,7 +195,7 @@ int main(int argc, char *argv[])
created_lock = 0, created_signal = 0, created_debug = 0;
#ifdef DEBUG_DURATION
time_t durationupdate;
double idle_duration, isdn_duration, port_duration, epoint_duration, call_duration, message_duration, admin_duration;
double idle_duration, isdn_duration, port_duration, epoint_duration, join_duration, message_duration, admin_duration;
double start_d;
#endif
int idletime = 0, idlecheck = 0;
@ -527,23 +527,23 @@ BUDETECT
start_d = now_d;
#endif
/* loop through all calls and call their handler */
call_again:
call = call_first;
while(call)
/* loop through all joins and call their handler */
join_again:
join = join_first;
while(join)
{
debug_prefix = "call";
debug_prefix = "join";
debug_count++;
ret = call->handler();
ret = join->handler();
if (ret)
all_idle = 0;
if (ret < 0) /* call has been destroyed */
goto call_again;
call = call->next;
if (ret < 0) /* join has been destroyed */
goto join_again;
join = join->next;
}
#ifdef DEBUG_DURATION
GET_NOW();
call_duration += (now_d - start_d);
join_duration += (now_d - start_d);
start_d = now_d;
#endif
@ -575,33 +575,33 @@ BUDETECT
}
break;
case EPOINT_TO_CALL:
debug_prefix = "msg epoint->call";
call = find_call_id(message->id_to);
if (call)
case EPOINT_TO_JOIN:
debug_prefix = "msg epoint->join";
join = find_join_id(message->id_to);
if (join)
{
call->message_epoint(message->id_from, message->type, &message->param);
join->message_epoint(message->id_from, message->type, &message->param);
} else
{
PDEBUG(DEBUG_MSG, "Warning: message %s from endpoint %d to call %d. call doesn't exist anymore\n", messages_txt[message->type], message->id_from, message->id_to);
PDEBUG(DEBUG_MSG, "Warning: message %s from endpoint %d to join %d. join doesn't exist anymore\n", messages_txt[message->type], message->id_from, message->id_to);
}
break;
case CALL_TO_EPOINT:
debug_prefix = "msg call->epoint";
case JOIN_TO_EPOINT:
debug_prefix = "msg join->epoint";
epoint = find_epoint_id(message->id_to);
if (epoint)
{
if (epoint->ep_app)
{
epoint->ep_app->ea_message_call(message->id_from, message->type, &message->param);
epoint->ep_app->ea_message_join(message->id_from, message->type, &message->param);
} else
{
PDEBUG(DEBUG_MSG, "Warning: message %s from call %d to endpoint %d. endpoint doesn't have an application.\n", messages_txt[message->type], message->id_from, message->id_to);
PDEBUG(DEBUG_MSG, "Warning: message %s from join %d to endpoint %d. endpoint doesn't have an application.\n", messages_txt[message->type], message->id_from, message->id_to);
}
} else
{
PDEBUG(DEBUG_MSG, "Warning: message %s from call %d to endpoint %d. endpoint doesn't exist anymore.\n", messages_txt[message->type], message->id_from, message->id_to);
PDEBUG(DEBUG_MSG, "Warning: message %s from join %d to endpoint %d. endpoint doesn't exist anymore.\n", messages_txt[message->type], message->id_from, message->id_to);
}
break;
@ -665,15 +665,15 @@ BUDETECT
if (durationupdate != now)
{
durationupdate = now;
printf("Idle:%3d ISDN:%3d Port:%3d Epoint:%3d Call:%3d Message:%3d Admin:%3d\n",
printf("Idle:%3d ISDN:%3d Port:%3d Epoint:%3d Join:%3d Message:%3d Admin:%3d\n",
(int)(idle_duration*100),
(int)(isdn_duration*100),
(int)(port_duration*100),
(int)(epoint_duration*100),
(int)(call_duration*100),
(int)(join_duration*100),
(int)(message_duration*100),
(int)(admin_duration*100));
idle_duration = isdn_duration = port_duration = epoint_duration = call_duration = message_duration = admin_duration = 0;
idle_duration = isdn_duration = port_duration = epoint_duration = join_duration = message_duration = admin_duration = 0;
}
#else
GET_NOW();
@ -686,7 +686,12 @@ BUDETECT
idletime += 4000;
}
}
printf("LCR terminated\n");
SPRINT(tracetext, "%s terminated", NAME);
printf("%s\n", tracetext);
start_trace(0, NULL, NULL, NULL, 0, 0, 0, tracetext);
if (ret)
add_trace("error", NULL, "%d", ret);
end_trace();
ret=0;
/* free all */
@ -725,7 +730,7 @@ free:
}
epoint_first = NULL;
debug_count++;
call_free();
join_free();
/* free interfaces */
if (interface_first)
@ -796,9 +801,9 @@ free:
ret = -1; \
}
MEMCHECK("",memuse)
MEMCHECK("memory block(s) left (port.cpp)",pmemuse)
MEMCHECK("memory block(s) left (epoint.cpp)",ememuse)
MEMCHECK("memory block(s) left (call.cpp)",cmemuse)
MEMCHECK("memory block(s) left (port.cpp ...)",pmemuse)
MEMCHECK("memory block(s) left (epoint*.cpp ...)",ememuse)
MEMCHECK("memory block(s) left (join*.cpp)",cmemuse)
MEMCHECK("memory block(s) left (message.c)",mmemuse)
MEMCHECK("memory block(s) left (route.c)",rmemuse)
MEMCHECK("memory block(s) left (args)",amemuse)
@ -807,14 +812,6 @@ free:
MEMCHECK("file handler(s) left",fhuse)
/* take me out */
if (ret == 999)
exit(0);
SPRINT(tracetext, "%s exit", NAME);
printf("%s\n", tracetext);
start_trace(0, NULL, NULL, NULL, 0, 0, 0, tracetext);
if (ret)
add_trace("error", NULL, "%d", ret);
end_trace();
return(ret);
}

10
main.h
View File

@ -1,6 +1,6 @@
/*****************************************************************************\
** **
** LCR **
** Linux Call Router **
** **
**---------------------------------------------------------------------------**
** Copyright: Andreas Eversberg **
@ -44,7 +44,7 @@ void debug(const char *function, int line, char *prefix, char *buffer);
//#define DEBUG_KNOCK 0x0140
#define DEBUG_VBOX 0x0180
#define DEBUG_EPOINT 0x0200
#define DEBUG_CALL 0x0400
#define DEBUG_JOIN 0x0400
#define DEBUG_VERSATEL 0x0800
#define DEBUG_CRYPT 0x1000
#define DEBUG_ROUTE 0x2000
@ -130,9 +130,9 @@ extern "C" {
#include "mISDN.h"
#include "dss1.h"
#include "vbox.h"
#include "call.h"
#include "callpbx.h"
#include "callasterisk.h"
#include "join.h"
#include "joinpbx.h"
#include "joinasterisk.h"
#include "cause.h"
#include "alawulaw.h"
#include "tones.h"

View File

@ -120,7 +120,7 @@ enum { /* diversion types */
enum { /* isdnsignal */
mISDNSIGNAL_VOLUME, /* change volume */
mISDNSIGNAL_CONF, /* joint/split conference */
mISDNSIGNAL_CALLDATA, /* data required by call instance */
mISDNSIGNAL_JOINDATA, /* data required by join instance */
mISDNSIGNAL_ECHO, /* enable/disable echoe */
mISDNSIGNAL_DELAY, /* use delay or adaptive jitter */
};
@ -261,7 +261,7 @@ struct param_mISDNsignal {
int rxvol;
int txvol;
int conf;
int calldata;
int joindata;
int tone;
int echo;
int delay;
@ -287,7 +287,7 @@ union parameter {
struct park_info parkinfo; /* MESSAGE_SUSPEND, MESSAGE_RESUME */
int state; /* MESSAGE_TIMEOUT */
int knock; /* MESSAGE_KNOCK 0=off !0=on */
int channel; /* MESSAGE_CHANNEL see RELATION_CHANNEL_* (call.h) */
int channel; /* MESSAGE_CHANNEL see RELATION_CHANNEL_* (join.h) */
struct param_data data; /* MESSAGE_DATA */
struct param_play play; /* MESSAGE_VBOX_PLAY */
int speed; /* MESSAGE_VBOX_PLAY_SPEED */
@ -299,8 +299,8 @@ union parameter {
enum { /* message flow */
PORT_TO_EPOINT,
EPOINT_TO_CALL,
CALL_TO_EPOINT,
EPOINT_TO_JOIN,
JOIN_TO_EPOINT,
EPOINT_TO_PORT,
};

View File

@ -208,7 +208,7 @@ static char *print_trace(int detail, int port, char *interface, char *caller, ch
SCAT(trace_string, "--");
}
if (trace.serial)
SPRINT(buffer, "(%d): %s", trace.serial, trace.name[0]?trace.name:"<unknown>");
SPRINT(buffer, "(%lu): %s", trace.serial, trace.name[0]?trace.name:"<unknown>");
else
SPRINT(buffer, ": %s", trace.name[0]?trace.name:"<unknown>");
SCAT(trace_string, buffer);

View File

@ -27,7 +27,7 @@ struct trace {
/* type */
int category;
int serial;
unsigned long serial;
char name[64];
/* elements */