From 6552bc36271c4926a8ac5615f4f84f7391034732 Mon Sep 17 00:00:00 2001 From: Super User Date: Sun, 12 Aug 2007 10:16:19 +0200 Subject: [PATCH] fix --- Makefile | 2 +- asterisk_client.c | 76 ++++++++++++++++++++++++++++++++++++++-- dss1.cpp | 18 +++++----- joinremote.cpp | 22 ++---------- joinremote.h | 2 +- mISDN.cpp | 102 ++++++++++++++++++++++++++++++++++-------------------- mISDN.h | 7 ++-- message.txt | 2 -- 8 files changed, 157 insertions(+), 74 deletions(-) diff --git a/Makefile b/Makefile index a0cc34f..4129c90 100644 --- a/Makefile +++ b/Makefile @@ -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. diff --git a/asterisk_client.c b/asterisk_client.c index 13ab261..f15564b 100644 --- a/asterisk_client.c +++ b/asterisk_client.c @@ -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 @@ -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 diff --git a/dss1.cpp b/dss1.cpp index 9a6a922..4a3f3a6 100644 --- a/dss1.cpp +++ b/dss1.cpp @@ -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) diff --git a/joinremote.cpp b/joinremote.cpp index f2c08b7..9dd16fd 100644 --- a/joinremote.cpp +++ b/joinremote.cpp @@ -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(¶m, 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, ¶m)<0) + if (admin_message_from_join(remote_id, ref, MESSAGE_BCHANNEL, ¶m)<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; } } diff --git a/joinremote.h b/joinremote.h index f80d0d9..b8d2cae 100644 --- a/joinremote.h +++ b/joinremote.h @@ -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); diff --git a/mISDN.cpp b/mISDN.cpp index bc1339f..67d649e 100644 --- a/mISDN.cpp +++ b/mISDN.cpp @@ -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: diff --git a/mISDN.h b/mISDN.h index 90ec032..3d231f4 100644 --- a/mISDN.h +++ b/mISDN.h @@ -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); diff --git a/message.txt b/message.txt index 0c770a3..d6c2dfe 100644 --- a/message.txt +++ b/message.txt @@ -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. -- 2.13.6