This commit is contained in:
Super User 2007-08-12 10:16:19 +02:00
parent b88911b990
commit 6552bc3627
8 changed files with 157 additions and 74 deletions

View File

@ -10,7 +10,7 @@
#*****************************************************************************/
WITH-CRYPTO = 42 # comment this out, if no libcrypto should be used
WITH-ASTERISK = 42 # comment this out, if you don't require built-in Asterisk channel driver.
#WITH-ASTERISK = 42 # comment this out, if you don't require built-in Asterisk channel driver.
#WITH-SOCKET = 42 # compile for socket based mISDN (
# note: check your location and the names of libraries.

View File

@ -25,7 +25,7 @@ Make a MESSAGE_SETUP or receive a MESSAGE_SETUP with the reference.
To release call and reference, send or receive MESSAGE_RELEASE.
From that point on, the ref is not valid, so no other message may be sent
with that reference.
*/
#include <stdio.h>
@ -44,6 +44,7 @@ with that reference.
#include "extension.h"
#include "message.h"
#include "admin.h"
#include "aserisk_client.h"
int sock;
@ -55,7 +56,7 @@ struct admin_list {
/*
* enque message from asterisk
*/
int admin_asterisk(int message_type, union parameter *param)
int send_message(int message_type, unsigned long ref, union parameter *param)
{
struct admin_list *admin, **adminp;
@ -66,11 +67,81 @@ int admin_asterisk(int message_type, union parameter *param)
*adminp = admin;
admin->msg.type = message_type;
admin->msg.ref = ref;
memcpy(&admin->msg.param, param, sizeof(union parameter));
return(0);
}
/*
* message received from LCR
*/
int receive_message(int message_type, unsigned long ref, union parameter *param)
{
union parameter newparam;
memset(&newparam, 0, sizeof(union parameter));
/* handle bchannel message*/
if (message_type == MESSAGE_BCHANNEL)
{
switch(param.bchannel.type)
{
case BCHANNEL_ASSIGN:
if (find_channel_addr(param->bchannel.addr))
{
fprintf(stderr, "error: bchannel addr %x already assigned.\n", param->bchannel.addr);
return(-1);
}
/* create channel */
channel = alloc_channel();
channel.addr = param->bchannel.addr;
/* in case, ref is not set, this channel instance must
* be created until it is removed again by LCR */
channel.ref = param->bchannel.ref;
/* link to call */
if ((call = find_call_ref(param->bchannel.ref)))
{
call.addr = param->bchannel.addr;
}
#warning open stack
/* acknowledge */
newparam.bchannel.type = BCHANNEL_ASSIGN_ACK;
newparam.bchannel.addr = param->bchannel.addr;
send_message(MESSAGE_BCHANNEL, 0, &newparam);
break;
case BCHANNEL_REMOVE:
if (!(channel = find_channel_addr(param->bchannel.addr)))
{
fprintf(stderr, "error: bchannel addr %x already assigned.\n", param->bchannel.addr);
return(-1);
}
/* unlink from call */
if ((call = find_call_ref(channel->ref)))
{
call.addr = 0;
}
/* remove channel */
free_channel(channel);
#warning close stack
/* acknowledge */
newparam.bchannel.type = BCHANNEL_REMOVE_ACK;
newparam.bchannel.addr = param->bchannel.addr;
send_message(MESSAGE_BCHANNEL, 0, &newparam);
break;
default:
fprintf(stderr, "received unknown bchannel message %d\n", param.bchannel.type);
}
return(0);
}
switch(message_type)
return(0);
}
/* asterisk handler
* warning! not thread safe
@ -102,6 +173,7 @@ int handle_socket(void)
fprintf(stderr, "Socket received illegal message %d\n", msg.message);
return(-1); // socket error
}
receive_message(msg.type, msg.ref, &msg.param);
printf("message received %d\n", msg.u.msg.type);
work = 1;
} else

View File

@ -164,7 +164,7 @@ int Pdss1::received_first_reply_to_setup(unsigned long prim, int channel, int ex
end_trace();
/* activate our exclusive channel */
bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE, p_m_exportremote);
bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
} else
if (p_m_b_channel)
{
@ -185,7 +185,7 @@ int Pdss1::received_first_reply_to_setup(unsigned long prim, int channel, int ex
add_trace("connect", "channel", "%d", p_m_b_channel);
end_trace();
p_m_b_exclusive = 1; // we are done
bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE, p_m_exportremote);
bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
return(0);
}
@ -212,7 +212,7 @@ int Pdss1::received_first_reply_to_setup(unsigned long prim, int channel, int ex
end_trace();
/* activate channel given by remote */
bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE, p_m_exportremote);
bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
} else
if (p_m_b_reserve)
{
@ -248,7 +248,7 @@ int Pdss1::received_first_reply_to_setup(unsigned long prim, int channel, int ex
end_trace();
/* activate channel given by remote */
bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE, p_m_exportremote);
bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
} else
{
/*** we sent 'no channel available' ***/
@ -277,7 +277,7 @@ int Pdss1::received_first_reply_to_setup(unsigned long prim, int channel, int ex
p_m_b_exclusive = 1; // we are done
/* activate channel given by remote */
bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE, p_m_exportremote);
bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
return(0);
}
@ -312,7 +312,7 @@ int Pdss1::received_first_reply_to_setup(unsigned long prim, int channel, int ex
p_m_b_exclusive = 1; // we are done
/* activate channel given by remote */
bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE, p_m_exportremote);
bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
}
return(0);
@ -731,7 +731,7 @@ void Pdss1::setup_ind(unsigned long prim, unsigned long dinfo, void *data)
p_m_delete = 1;
return;
}
bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE, p_m_exportremote);
bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
/* create endpoint */
if (p_epointlist)
@ -1473,7 +1473,7 @@ void Pdss1::retrieve_ind(unsigned long prim, unsigned long dinfo, void *data)
cause = -ret;
goto reject;
}
bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE, p_m_exportremote);
bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
/* set hold state */
p_m_hold = 0;
@ -1645,7 +1645,7 @@ void Pdss1::resume_ind(unsigned long prim, unsigned long dinfo, void *data)
p_m_delete = 1;
return;
}
bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE, p_m_exportremote);
bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
/* create endpoint */
if (p_epointlist)

View File

@ -123,32 +123,16 @@ void JoinRemote::message_remote(int message_type, union parameter *param)
}
}
void message_bchannel_to_join(int serial, int type, unsigned long addr)
void message_bchannel_to_join(unsigned long remote_id, unsigned long ref, int type, unsigned long addr)
{
union parameter param;
class Join *join;
class JoinRemote *joinremote;
/* find join serial */
join = find_join_id(serial);
if (!join)
{
PDEBUG(DEBUG_JOIN | DEBUG_BCHANNEL, "Join %d not found\n", serial);
return;
}
if (!join->j_type != JOIN_TYPE_REMOTE)
{
PERROR("Join %d not of remote type. This shall not happen.\n", serial);
return;
}
joinremote = (class JoinRemote *)join;
memset(&param, 0, sizeof(union parameter));
param.bchannel.type = type;
param.bchannel.addr = addr;
if (admin_message_from_join(joinremote->j_remote_id, joinremote->j_serial, MESSAGE_BCHANNEL, &param)<0)
if (admin_message_from_join(remote_id, ref, MESSAGE_BCHANNEL, &param)<0)
{
PERROR("No socket with remote application '%s' found, this shall not happen. Closing socket shall cause release of all joins.\n", joinremote->j_remote_name);
PERROR("No socket with remote id %d found, this happens, if the socket is closed before all bchannels are imported.\n", remote_id);
return;
}
}

View File

@ -24,4 +24,4 @@ class JoinRemote : public Join
};
void message_bchannel_to_join(int serial, int type, unsigned long addr);
void message_bchannel_to_join(unsigned long remote_id, unsigned long ref, int type, unsigned long addr);

102
mISDN.cpp
View File

@ -159,7 +159,8 @@ PmISDN::PmISDN(int type, mISDNport *mISDNport, char *portname, struct port_setti
p_m_dtmf = !mISDNport->ifport->nodtmf;
p_m_timeout = 0;
p_m_timer = 0;
p_m_exportremote = 0; /* channel shall be exported to given remote */
p_m_remote_ref = 0; /* channel shall be exported to given remote */
p_m_remote_id = 0; /* channel shall be exported to given remote */
/* audio */
p_m_load = 0;
@ -622,6 +623,19 @@ The bchannel is not used by remote application.
All actions taken on these events depend on the current bchannel's state and if it is linked to a Port class.
if an export request is receive by remote application, p_m_exportremote is set.
the b_remotejoin[index] indicates if linked port shall be exported.
- set on export request from remote application (if port is assigned)
- set on channel use, if requested by remote application (p_m_exportremote)
- cleared on drop request
the bchannel will be exported with ref and stack given. remote application uses the ref to link bchannel to the call.
the bchannel will be imported with stack given only. remote application must store stack id with the bchannel process.
the bchannel import/export is acknowledged with stack given.
if exporting, b_remotesocket[index] is set to the remote socket id.
if importing has been acknowledged. b_remotesockt[index] is cleared.
*/
/*
@ -631,13 +645,20 @@ All actions taken on these events depend on the current bchannel's state and if
* - event is the B_EVENT_* value
* - port is the PmISDN class pointer
*/
void bchannel_event(struct mISDNport *mISDNport, int i, int event, unsigned long to_remote)
void bchannel_event(struct mISDNport *mISDNport, int i, int event)
{
class PmISDN *b_port = mISDNport->b_port[i];
int state = mISDNport->b_state[i];
unsigned long remote = mISDNport->b_remote[i];
unsigned long p_m_remote_ref = 0;
unsigned long p_m_remote_id = 0;
unsigned long addr = mISDNport->b_addr[i];
if (b_port)
{
p_m_remote_id = b_port->p_m_remote_id;
p_m_remote_ref = b_port->p_m_remote_ref;
}
switch(event)
{
case B_EVENT_USE:
@ -647,19 +668,16 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event, unsigned long
switch(state)
{
case B_STATE_IDLE:
if (remote)
PDEBUG(DEBUG_BCHANNEL, "idle channels don't have remote link.\n");
if (to_remote)
if (p_m_remote_id)
{
/* export bchannel */
mISDNport->b_remote[i] = remote = to_remote;
message_bchannel_to_join(remote, BCHANNEL_ASSIGN, addr);
message_bchannel_to_join(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, addr);
chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
add_trace("type", NULL, "assign");
add_trace("stack", "address", "%x", addr);
end_trace();
state = B_STATE_EXPORTING;
mISDNport->b_remote_id[i] = p_m_remote_id;
} else
{
/* create stack and send activation request */
@ -692,22 +710,24 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event, unsigned long
case B_EVENT_EXPORTREQUEST:
/* special case where the bchannel is requested by remote */
if (remote)
if (!p_m_remote_id)
{
PERROR("channel for join %d already exported to join %d, please correct.\n", to_remote, remote);
PERROR("export request without remote channel set, please correct.\n");
break;
}
mISDNport->b_remote[i] = remote = to_remote;
switch(state)
{
case B_STATE_IDLE:
/* in case, the bchannel is exported right after seize_bchannel */
/* export bchannel */
message_bchannel_to_join(remote, BCHANNEL_ASSIGN, addr);
/* p_m_remote_id is set, when this event happens. */
message_bchannel_to_join(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, addr);
chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
add_trace("type", NULL, "assign");
add_trace("stack", "address", "%x", addr);
end_trace();
state = B_STATE_EXPORTING;
mISDNport->b_remote_id[i] = p_m_remote_id;
break;
case B_STATE_ACTIVATING:
@ -739,7 +759,7 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event, unsigned long
switch(state)
{
case B_STATE_ACTIVATING:
if (b_port && !remote)
if (b_port && !p_m_remote_id)
{
/* bchannel is active and used by Port class, so we configure bchannel */
_bchannel_configure(mISDNport, i);
@ -761,14 +781,14 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event, unsigned long
switch(state)
{
case B_STATE_EXPORTING:
if (b_port && remote && to_remote==remote)
if (b_port && p_m_remote_id)
{
/* remote export done */
state = B_STATE_REMOTE;
} else
{
/* bchannel is now exported, but we need bchannel back OR bchannel is not used anymore OR remote has changed, so reimport, to later export to new remote */
message_bchannel_to_join(remote, BCHANNEL_REMOVE, addr);
/* bchannel is now exported, but we need bchannel back OR bchannel is not used anymore, so reimport, to later export to new remote */
message_bchannel_to_join(mISDNport->b_remote_id[i], 0, BCHANNEL_REMOVE, addr);
chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
add_trace("type", NULL, "remove");
add_trace("stack", "address", "%x", addr);
@ -804,7 +824,7 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event, unsigned long
case B_STATE_REMOTE:
/* bchannel is exported, so we re-import */
message_bchannel_to_join(remote, BCHANNEL_REMOVE, addr);
message_bchannel_to_join(mISDNport->b_remote_id[i], 0, BCHANNEL_REMOVE, addr);
chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
add_trace("type", NULL, "remove");
add_trace("stack", "address", "%x", addr);
@ -835,14 +855,15 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event, unsigned long
if (b_port)
{
/* bchannel is now deactivate, but is requied by Port class, so we reactivate / export */
if (remote)
if (p_m_remote_id)
{
message_bchannel_to_join(remote, BCHANNEL_ASSIGN, addr);
message_bchannel_to_join(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, addr);
chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
add_trace("type", NULL, "assign");
add_trace("stack", "address", "%x", addr);
end_trace();
state = B_STATE_EXPORTING;
mISDNport->b_remote_id[i] = p_m_remote_id;
} else
{
if (_bchannel_create(mISDNport, i))
@ -864,17 +885,19 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event, unsigned long
{
case B_STATE_IMPORTING:
state = B_STATE_IDLE;
mISDNport->b_remote_id[i] = 0;
if (b_port)
{
/* bchannel is now imported, but is requied by Port class, so we reactivate / export */
if (remote)
if (p_m_remote_id)
{
message_bchannel_to_join(remote, BCHANNEL_ASSIGN, addr);
message_bchannel_to_join(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, addr);
chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
add_trace("type", NULL, "assign");
add_trace("stack", "address", "%x", addr);
end_trace();
state = B_STATE_EXPORTING;
mISDNport->b_remote_id[i] = p_m_remote_id;
} else
{
if (_bchannel_create(mISDNport, i))
@ -883,10 +906,6 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event, unsigned long
state = B_STATE_ACTIVATING;
}
}
} else
{
/* not exported anymore */
mISDNport->b_remote[i] = 0;
}
break;
@ -970,7 +989,6 @@ seize:
/* link Port */
p_m_mISDNport->b_port[i] = this;
p_m_mISDNport->b_remote[i] = p_m_exportremote;
p_m_b_index = i;
p_m_b_channel = channel;
p_m_b_exclusive = exclusive;
@ -1006,7 +1024,7 @@ void PmISDN::drop_bchannel(void)
PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) dropping bchannel\n", p_name);
if (p_m_mISDNport->b_state[p_m_b_index] != B_STATE_IDLE)
bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_DROP, 0);
bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_DROP);
p_m_mISDNport->b_port[p_m_b_index] = NULL;
p_m_b_index = -1;
p_m_b_channel = 0;
@ -1052,16 +1070,21 @@ void message_bchannel_from_join(class JoinRemote *joinremote, int type, unsigned
isdnport = (class PmISDN *)port;
/* assign */
if (isdnport->p_m_exportremote)
if (isdnport->p_m_remote_id)
{
PERROR("join %d recevied bchannel request from remote, but channel is already assinged.\n", joinremote->j_serial);
break;
}
chan_trace_header(isdnport->p_m_mISDNport, isdnport, "MESSAGE_BCHANNEL (from remote application)", DIRECTION_NONE);
mISDNport = isdnport->p_m_mISDNport;
i = isdnport->p_m_b_index;
chan_trace_header(mISDNport, isdnport, "MESSAGE_BCHANNEL (from remote application)", DIRECTION_NONE);
add_trace("type", NULL, "export request");
isdnport->p_m_exportremote = joinremote->j_serial;
if (isdnport->p_m_mISDNport && isdnport->p_m_b_index>=0)
bchannel_event(isdnport->p_m_mISDNport, isdnport->p_m_b_index, B_EVENT_EXPORTREQUEST, joinremote->j_serial);
isdnport->p_m_remote_ref = joinremote->j_serial;
isdnport->p_m_remote_id = joinremote->j_remote_id;
if (mISDNport && i>=0)
{
bchannel_event(mISDNport, i, B_EVENT_EXPORTREQUEST);
}
end_trace();
break;
@ -1083,13 +1106,18 @@ void message_bchannel_from_join(class JoinRemote *joinremote, int type, unsigned
break;
mISDNport = mISDNport->next;
}
if (!mISDNport)
{
PERROR("received assign/remove ack for addr=%x, but address does not exist.\n", addr);
break;
}
/* mISDNport may now be set or NULL */
/* set */
chan_trace_header(mISDNport, mISDNport->b_port[i], "MESSAGE_BCHANNEL (from remote application)", DIRECTION_NONE);
add_trace("type", NULL, (type==BCHANNEL_ASSIGN_ACK)?"assign_ack":"remove_ack");
if (mISDNport && i>=0)
bchannel_event(mISDNport, i, (type==BCHANNEL_ASSIGN_ACK)?B_EVENT_EXPORTED:B_EVENT_IMPORTED, 0);
bchannel_event(mISDNport, i, (type==BCHANNEL_ASSIGN_ACK)?B_EVENT_EXPORTED:B_EVENT_IMPORTED);
end_trace();
break;
default:
@ -2078,7 +2106,7 @@ int mISDN_handler(void)
PERROR("unhandled b-establish (prim 0x%x address 0x%x).\n", frm->prim, frm->addr);
break;
}
bchannel_event(mISDNport, i, B_EVENT_ACTIVATED, 0);
bchannel_event(mISDNport, i, B_EVENT_ACTIVATED);
break;
case PH_DEACTIVATE | INDICATION:
@ -2098,7 +2126,7 @@ int mISDN_handler(void)
PERROR("unhandled b-release (prim 0x%x address 0x%x).\n", frm->prim, frm->addr);
break;
}
bchannel_event(mISDNport, i, B_EVENT_DEACTIVATED, 0);
bchannel_event(mISDNport, i, B_EVENT_DEACTIVATED);
break;
default:

View File

@ -43,7 +43,7 @@ struct mISDNport {
int b_stid[128];
unsigned long b_addr[128];
int b_state[128]; /* statemachine, 0 = IDLE */
unsigned long b_remote[128]; /* if remote application requires bchannel */
unsigned long b_remote_id[128]; /* the socket currently exported */
int procids[128]; /* keep track of free ids */
int locally; /* local causes are sent as local causes not remote */
msg_queue_t downqueue; /* l4->l3 */
@ -83,7 +83,7 @@ int stack2manager_nt(void *dat, void *arg);
int stack2manager_te(struct mISDNport *mISDNport, msg_t *msg);
void chan_trace_header(struct mISDNport *mISDNport, class PmISDN *port, char *msgtext, int direction);
void l1l2l3_trace_header(struct mISDNport *mISDNport, class PmISDN *port, unsigned long prim, int direction);
void bchannel_event(struct mISDNport *mISDNport, int i, int event, unsigned long to_remote);
void bchannel_event(struct mISDNport *mISDNport, int i, int event);
void message_bchannel_from_join(class JoinRemote *joinremote, int type, unsigned long addr);
@ -146,7 +146,8 @@ class PmISDN : public Port
int p_m_hold; /* if port is on hold */
unsigned long p_m_timeout; /* timeout of timers */
time_t p_m_timer; /* start of timer */
unsigned char p_m_exportremote; /* join to export bchannel to */
unsigned char p_m_remote_ref; /* join to export bchannel to */
unsigned char p_m_remote_id; /* sock to export bchannel to */
int seize_bchannel(int channel, int exclusive); /* requests / reserves / links bchannels, but does not open it! */
void drop_bchannel(void);

View File

@ -182,8 +182,6 @@ MESSAGE_BCHANNEL
MESSAGE_RELEASE
- will be received or sent to release call and ref.
- also bchannel socket must be closed AND BCHANNEL_REMOVE_ACK must be sent!
the bchannel is in exported state until acked by the remote application.
what happenes to channels that are not acked?
-> one solution may be: they are blocked until the port is unloaded/unblocked.