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>
#include "extension.h"
#include "message.h"
#include "admin.h"
+#include "aserisk_client.h"
int sock;
/*
* 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;
*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
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
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)
{
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);
}
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)
{
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' ***/
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);
}
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);
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)
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;
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)
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;
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.
+
*/
/*
* - 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:
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 */
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:
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);
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);
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);
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))
{
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))
state = B_STATE_ACTIVATING;
}
}
- } else
- {
- /* not exported anymore */
- mISDNport->b_remote[i] = 0;
}
break;
/* 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;
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;
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;
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:
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:
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: