added exporting/importing bchannel stacks to the remote application
authorSuper User <root@isdn.jolly.ten>
Sat, 11 Aug 2007 13:57:58 +0000 (15:57 +0200)
committerSuper User <root@isdn.jolly.ten>
Sat, 11 Aug 2007 13:57:58 +0000 (15:57 +0200)
13 files changed:
admin_client.c
admin_server.c
apppbx.cpp
dss1.cpp
endpoint.cpp
endpoint.h
joinpbx.cpp
joinremote.cpp
joinremote.h
mISDN.cpp
mISDN.h
message.h
message.txt

index 6bf964c..dac2b78 100644 (file)
@@ -717,12 +717,41 @@ char *admin_state(int sock, char *argv[])
                                                        if (m[i].u.i.l2link && m[i].u.i.block==0)
                                                        {
                                                                ptmp:
-                                                               color((m[i].u.i.busy[j])?yellow:blue);
-                                                               addstr((m[i].u.i.busy[j])?"busy":"idle");
+                                                               switch(m[i].u.i.busy[j])
+                                                               {
+                                                                       case B_STATE_IDLE:
+                                                                       color(blue);
+                                                                       addstr("idle    ");
+                                                                       break;
+                                                                       case B_STATE_ACTIVATING:
+                                                                       color(yellow);
+                                                                       addstr("act'ing ");
+                                                                       break;
+                                                                       case B_STATE_ACTIVE:
+                                                                       color(green);
+                                                                       addstr("busy    ");
+                                                                       break;
+                                                                       case B_STATE_DEACTIVATING:
+                                                                       color(yellow);
+                                                                       addstr("dact'ing");
+                                                                       break;
+                                                                       case B_STATE_EXPORTING:
+                                                                       color(yellow);
+                                                                       addstr("exp'ing ");
+                                                                       break;
+                                                                       case B_STATE_REMOTE:
+                                                                       color(green);
+                                                                       addstr("remote  ");
+                                                                       break;
+                                                                       case B_STATE_IMPORTING:
+                                                                       color(yellow);
+                                                                       addstr("imp'ing ");
+                                                                       break;
+                                                               }
                                                        } else
                                                        {
                                                                color(red);
-                                                               addstr("blk ");
+                                                               addstr("blocked ");
                                                        }
                                                        if (m[i].u.i.port[j])
                                                        {
index f1275a6..6b0647b 100644 (file)
@@ -107,7 +107,7 @@ void free_connection(struct admin_list *admin)
                                memset(&param, 0, sizeof(param));
                                param.disconnectinfo.cause = CAUSE_OUTOFORDER;
                                param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
-                               ((class JoinRemote *)join)->message_remote(0, MESSAGE_RELEASE, &param);
+                               ((class JoinRemote *)join)->message_remote(MESSAGE_RELEASE, &param);
                                /* join is now destroyed, so we go to next join */
                        }
                        join = joinnext;
@@ -511,7 +511,7 @@ int admin_call(struct admin_list *admin, struct admin_message *msg)
        class Endpoint          *epoint;
        class EndpointAppPBX    *apppbx;
 
-       if (!(epoint = new Endpoint(0, 0, 0)))
+       if (!(epoint = new Endpoint(0, 0)))
                FATAL("No memory for Endpoint instance\n");
        if (!(epoint->ep_app = apppbx = new DEFAULT_ENDPOINT_APP(epoint)))
                FATAL("No memory for Endpoint Application instance\n");
@@ -641,6 +641,17 @@ int admin_message_to_join(struct admin_msg *msg, char *remote_name, int sock_id)
                return(0);
        }
 
+       /* bchannel message
+        * no ref given for *_ack */
+       if (msg->type == MESSAGE_BCHANNEL)
+       if (msg->param.bchannel.type == BCHANNEL_ASSIGN_ACK
+        || msg->param.bchannel.type == BCHANNEL_REMOVE_ACK)
+       {
+               /* no ref, but address */
+               message_bchannel_from_join(NULL, msg->param.bchannel.type, msg->param.bchannel.addr);
+               return(0);
+       }
+       
        /* check for ref */
        if (!msg->ref)
        {
@@ -675,7 +686,7 @@ int admin_message_to_join(struct admin_msg *msg, char *remote_name, int sock_id)
        }
 
        /* send message */
-       ((class JoinRemote *)join)->message_remote(msg->ref, msg->type, &msg->param);
+       ((class JoinRemote *)join)->message_remote(msg->type, &msg->param);
 
        return(0);
 }
index 1cef961..375980a 100644 (file)
@@ -2901,14 +2901,15 @@ void EndpointAppPBX::ea_message_port(unsigned long port_id, int message_type, un
                port_resume(portlist, message_type, param);
                break;
 
+#if 0
                /* port assigns bchannel */
-               case MESSAGE_BCHANNEL: /* indicates the assigned bchannel  */
-               case MESSAGE_BCHANNEL_FREE: /* requests bchannel back (e.g. when call is holded) */
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received bchannel assignment.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
+               case MESSAGE_BCHANNEL: /* bchannel assignment messafe */
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received bchannel message %d from port.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->bchannel.type);
                /* only one port is expected to be connected to bchannel */
                message = message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
                logmessage(message->type, &message->param, portlist->port_id, DIRECTION_IN);
                break;
+#endif
 
 
                default:
@@ -3459,7 +3460,7 @@ void EndpointAppPBX::join_notify(struct port_list *portlist, int message_type, u
        }
 }
 
-/* call sends messages to the endpoint
+/* JOIN sends messages to the endpoint
  */
 void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, union parameter *param)
 {
@@ -3468,7 +3469,7 @@ void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, un
 
        if (!join_id)
        {
-               PERROR("EPOINT(%d) error: call == NULL.\n", ea_endpoint->ep_serial);
+               PERROR("EPOINT(%d) error: JOIN == NULL.\n", ea_endpoint->ep_serial);
                return;
        }
 
@@ -3477,7 +3478,7 @@ void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, un
        /* send MESSAGE_DATA to port */
        if (message_type == MESSAGE_DATA)
        {
-               if (join_id == ea_endpoint->ep_join_id) // still linked with call
+               if (join_id == ea_endpoint->ep_join_id) // still linked with JOIN
                {
                        /* skip if no port relation */
                        if (!portlist)
@@ -3491,28 +3492,28 @@ void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, un
                }
        }
 
-//     PDEBUG(DEBUG_EPOINT, "EPOINT(%d) received message %d for active call (terminal %s, caller id %s state=%d)\n", ea_endpoint->ep_serial, message, e_ext.number, e_callerinfo.id, e_state);
+//     PDEBUG(DEBUG_EPOINT, "EPOINT(%d) received message %d for active JOIN (terminal %s, caller id %s state=%d)\n", ea_endpoint->ep_serial, message, e_ext.number, e_callerinfo.id, e_state);
        switch(message_type)
        {
-               /* CALL SENDS CRYPT message */
+               /* JOIN SENDS CRYPT message */
                case MESSAGE_CRYPT:
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received crypt message: '%d'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->crypt.type);
                join_crypt(portlist, message_type, param);
                break;
 
-               /* CALL sends INFORMATION message */
+               /* JOIN sends INFORMATION message */
                case MESSAGE_INFORMATION:
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received more digits: '%s'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->information.id);
                join_information(portlist, message_type, param);
                break;
 
-               /* CALL sends FACILITY message */
+               /* JOIN sends FACILITY message */
                case MESSAGE_FACILITY:
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received facility\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
                join_facility(portlist, message_type, param);
                break;
 
-               /* CALL sends OVERLAP message */
+               /* JOIN sends OVERLAP message */
                case MESSAGE_OVERLAP:
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received 'more info available'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
                if (e_state!=EPOINT_STATE_IN_SETUP
@@ -3524,7 +3525,7 @@ void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, un
                join_overlap(portlist, message_type, param);
                break;
 
-               /* CALL sends PROCEEDING message */
+               /* JOIN sends PROCEEDING message */
                case MESSAGE_PROCEEDING:
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s (caller id '%s') received proceeding\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
                if(e_state!=EPOINT_STATE_IN_OVERLAP)
@@ -3535,7 +3536,7 @@ void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, un
                join_proceeding(portlist, message_type, param);
                break;
 
-               /* CALL sends ALERTING message */
+               /* JOIN sends ALERTING message */
                case MESSAGE_ALERTING:
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received alerting\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
                if (e_state!=EPOINT_STATE_IN_OVERLAP
@@ -3547,7 +3548,7 @@ void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, un
                join_alerting(portlist, message_type, param);
                break;
 
-               /* CALL sends CONNECT message */
+               /* JOIN sends CONNECT message */
                case MESSAGE_CONNECT:
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received connect\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
                if (e_state!=EPOINT_STATE_IN_OVERLAP
@@ -3560,29 +3561,29 @@ void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, un
                join_connect(portlist, message_type, param);
                break;
 
-               /* CALL sends DISCONNECT/RELEASE message */
-               case MESSAGE_DISCONNECT: /* call disconnect */
-               case MESSAGE_RELEASE: /* call releases */
+               /* JOIN sends DISCONNECT/RELEASE message */
+               case MESSAGE_DISCONNECT: /* JOIN disconnect */
+               case MESSAGE_RELEASE: /* JOIN releases */
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received %s with cause %d location %d\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, (message_type==MESSAGE_DISCONNECT)?"disconnect":"release", param->disconnectinfo.cause, param->disconnectinfo.location);
                join_disconnect_release(message_type, param);
                break;
 
-               /* CALL sends SETUP message */
+               /* JOIN sends SETUP message */
                case MESSAGE_SETUP:
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint received setup from terminal='%s',id='%s' to id='%s' (dialing itype=%d)\n", ea_endpoint->ep_serial, param->setup.callerinfo.extension, param->setup.callerinfo.id, param->setup.dialinginfo.id, param->setup.dialinginfo.itype);
                join_setup(portlist, message_type, param);
                break;
 
-               /* CALL sends special mISDNSIGNAL message */
+               /* JOIN sends special mISDNSIGNAL message */
                case MESSAGE_mISDNSIGNAL: /* isdn message to port */
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received mISDNsignal message.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
                join_mISDNsignal(portlist, message_type, param);
                break;
 
-               /* call requests bchannel */
+#if 0
+               /* JOIN requests bchannel */
                case MESSAGE_BCHANNEL: /* indicates the need of own bchannel access */
-               case MESSAGE_BCHANNEL_FREE: /* indicates that the bchannel is free */
-               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received bchannel request.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
+               PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received bchannel assignment %d from join.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->bchannel.type);
                /* only one port is expected to be connected to bchannel */
                if (!portlist)
                        break;
@@ -3594,8 +3595,9 @@ void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, un
                message = message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
                logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
                break;
+#endif
 
-               /* CALL has pattern available */
+               /* JOIN has pattern available */
                case MESSAGE_PATTERN: /* indicating pattern available */
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received pattern availability.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
                if (!e_join_pattern)
@@ -3620,7 +3622,7 @@ void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, un
                }
                break;
 
-               /* CALL has no pattern available */
+               /* JOIN has no pattern available */
                case MESSAGE_NOPATTERN: /* indicating no pattern available */
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received pattern NOT available.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
                if (e_join_pattern)
@@ -3635,7 +3637,7 @@ void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, un
                break;
 
 #if 0
-               /* CALL (dunno at the moment) */
+               /* JOIN (dunno at the moment) */
                case MESSAGE_REMOTE_AUDIO:
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received audio remote request.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
                message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
@@ -3644,7 +3646,7 @@ void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, un
                break;
 #endif
 
-               /* CALL sends a notify message */
+               /* JOIN sends a notify message */
                case MESSAGE_NOTIFY:
                PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received notify.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
                join_notify(portlist, message_type, param);
@@ -4478,13 +4480,32 @@ void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsign
                end_trace();
                break;
 
+#if 0
                case MESSAGE_BCHANNEL:
-               case MESSAGE_BCHANNEL_FREE:
                trace_header("BCHANNEL", dir);
+               switch(param->bchannel.type)
+               {
+                       case BCHANNEL_REQUEST:
+                       add_trace("type", NULL, "request");
+                       break;
+                       case BCHANNEL_ASSIGN:
+                       add_trace("type", NULL, "assign");
+                       break;
+                       case BCHANNEL_ASSIGN_ACK:
+                       add_trace("type", NULL, "assign_ack");
+                       break;
+                       case BCHANNEL_REMOVE:
+                       add_trace("type", NULL, "remove");
+                       break;
+                       case BCHANNEL_REMOVE_ACK:
+                       add_trace("type", NULL, "remove_ack");
+                       break;
+               }
                if (param->bchannel.addr)
                        add_trace("address", NULL, "%x", param->bchannel.addr);
                end_trace();
                break;
+#endif
 
                default:
                PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message_type);
index a52f66e..9a6a922 100644 (file)
--- 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_ACTIVATE);
+               bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE, p_m_exportremote);
        } 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_ACTIVATE);
+                       bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE, p_m_exportremote);
                        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_ACTIVATE);
+               bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE, p_m_exportremote);
        } 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_ACTIVATE);
+               bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE, p_m_exportremote);
        } 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_ACTIVATE);
+                       bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE, p_m_exportremote);
                        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_ACTIVATE);
+               bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE, p_m_exportremote);
        }
        return(0);
 
@@ -731,12 +731,12 @@ 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_ACTIVATE);
+       bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE, p_m_exportremote);
 
        /* create endpoint */
        if (p_epointlist)
                FATAL("Incoming call but already got an endpoint.\n");
-       if (!(epoint = new Endpoint(p_serial, 0, 0)))
+       if (!(epoint = new Endpoint(p_serial, 0)))
                FATAL("No memory for Endpoint instance\n");
        if (!(epoint->ep_app = new DEFAULT_ENDPOINT_APP(epoint)))
                FATAL("No memory for Endpoint Application instance\n");
@@ -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_ACTIVATE);
+       bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE, p_m_exportremote);
 
        /* 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_ACTIVATE);
+       bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE, p_m_exportremote);
 
        /* create endpoint */
        if (p_epointlist)
index b5d6f64..e0f6365 100644 (file)
@@ -39,7 +39,7 @@ class Endpoint *find_epoint_id(unsigned long epoint_id)
 /*
  * endpoint constructor (link with either port or join id)
  */
-Endpoint::Endpoint(unsigned long port_id, unsigned long join_id, unsigned long use_epoint_id)
+Endpoint::Endpoint(unsigned long port_id, unsigned long join_id)
 {
        class Port *port;
        class Endpoint **epointpointer;
@@ -60,10 +60,7 @@ Endpoint::Endpoint(unsigned long port_id, unsigned long join_id, unsigned long u
        *epointpointer = this;
 
        /* serial */
-       if (use_epoint_id)
-               ep_serial = use_epoint_id;
-       else
-               ep_serial = epoint_serial++;
+       ep_serial = epoint_serial++;
 
        /* link to join or port */
        if (port_id)
index 460c0d7..a336beb 100644 (file)
@@ -22,7 +22,7 @@ struct port_list {
 class Endpoint
 {
        public:
-       Endpoint(unsigned long port_id, unsigned long join_id, unsigned long use_epoint_id);
+       Endpoint(unsigned long port_id, unsigned long join_id);
        ~Endpoint();
        class Endpoint          *next;          /* next in list */
        unsigned long           ep_serial;      /* a unique serial to identify */
index ff8fcd1..6d8b1b9 100644 (file)
@@ -983,7 +983,7 @@ int JoinPBX::out_setup(unsigned long epoint_id, int message_type, union paramete
        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, j_serial, 0);
+       epoint = new Endpoint(0, j_serial);
        if (!epoint)
                FATAL("No memory for Endpoint instance\n");
        if (!(epoint->ep_app = new DEFAULT_ENDPOINT_APP(epoint)))
index 3b7291c..f2c08b7 100644 (file)
@@ -37,12 +37,13 @@ JoinRemote::JoinRemote(unsigned long serial, char *remote_name, int remote_id) :
        j_remote_id = remote_id;
        j_type = JOIN_TYPE_REMOTE;
 
-       j_epoint_id = serial;
+       j_epoint_id = serial; /* this is the endpoint, if created by epoint */
        if (j_epoint_id)
                PDEBUG(DEBUG_JOIN, "New remote join connected to endpoint id %lu and application %s\n", j_epoint_id, remote_name);
 
        /* send new ref to remote socket */
        memset(&param, 0, sizeof(param));
+       /* the j_serial is assigned by Join() parent. this is sent as new ref */
        if (admin_message_from_join(j_remote_id, j_serial, MESSAGE_NEWREF, param)<0)
                FATAL("No socket with remote application '%s' found, this shall not happen. because we already created one.\n", j_remote_name);
 }
@@ -53,7 +54,6 @@ JoinRemote::JoinRemote(unsigned long serial, char *remote_name, int remote_id) :
  */
 JoinRemote::~JoinRemote()
 {
-
 }
 
 
@@ -87,7 +87,7 @@ void JoinRemote::message_epoint(unsigned long epoint_id, int message_type, union
        }
 }
 
-void JoinRemote::message_remote(unsigned long ref, int message_type, union parameter *param)
+void JoinRemote::message_remote(int message_type, union parameter *param)
 {
        struct message *message;
 
@@ -96,12 +96,22 @@ void JoinRemote::message_remote(unsigned long ref, int message_type, union param
        {
                class Endpoint          *epoint;
 
-               if (!(epoint = new Endpoint(0, j_serial, ref)))
+               if (!(epoint = new Endpoint(0, j_serial)))
                        FATAL("No memory for Endpoint instance\n");
+               j_epoint_id = epoint->ep_serial;
                if (!(epoint->ep_app = new DEFAULT_ENDPOINT_APP(epoint)))
                        FATAL("No memory for Endpoint Application instance\n");
        }
 
+       /* set serial on bchannel message
+        * also ref is given, so we send message with ref */
+       if (message_type == MESSAGE_BCHANNEL)
+       {
+               message_bchannel_from_join(this, param->bchannel.type, param->bchannel.addr);
+               return;
+       }
+       
+       /* cannot just forward, because param is not of container "struct message" */
        message = message_create(j_serial, j_epoint_id, JOIN_TO_EPOINT, message_type);
        memcpy(&message->param, param, sizeof(message->param));
        message_put(message);
@@ -113,5 +123,35 @@ void JoinRemote::message_remote(unsigned long ref, int message_type, union param
        }
 }
 
+void message_bchannel_to_join(int serial, 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)
+       {
+               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);
+               return;         
+       }
+}
+
 
 
index ac86467..f80d0d9 100644 (file)
@@ -15,7 +15,7 @@ class JoinRemote : public Join
        JoinRemote(unsigned long serial, char *remote_name, int remote_id);
        ~JoinRemote();
        void message_epoint(unsigned long epoint_id, int message, union parameter *param);
-       void message_remote(unsigned long ref, int message_type, union parameter *param);
+       void message_remote(int message_type, union parameter *param);
        int handler(void);
 
        int j_remote_id;
@@ -24,3 +24,4 @@ class JoinRemote : public Join
 }; 
 
 
+void message_bchannel_to_join(int serial, int type, unsigned long addr);
index 66c17ee..6196ee2 100644 (file)
--- a/mISDN.cpp
+++ b/mISDN.cpp
@@ -159,6 +159,7 @@ 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 */
 
        /* audio */
        p_m_load = 0;
@@ -472,7 +473,7 @@ failed:
 
 /*
  * subfunction for bchannel_event
- * activate request
+ * activate / deactivate request
  */
 static void _bchannel_activate(struct mISDNport *mISDNport, int i, int activate)
 {
@@ -582,21 +583,43 @@ It may be linked to a Port class, that likes to reactivate it.
 See above.
 After deactivating bchannel, and if not used, the bchannel becomes idle again.
 
+Also the bchannel may be exported, but only if the state is or becomes idle:
+
+- B_STATE_EXPORTING
+The bchannel assignment has been sent to the remove application.
+
+- B_STATE_REMOTE
+The bchannel assignment is acknowledged by the remote application.
+
+- B_STATE_IMPORTING
+The bchannel is re-imported by mISDN port object.
+
+- B_STATE_IDLE
+See above.
+After re-importing bchannel, and if not used, the bchannel becomes idle again.
+
 
 A bchannel can have the following events:
 
-- B_EVENT_ACTIVATE
+- B_EVENT_USE
 A bchannel is required by a Port class.
+The bchannel shall be exported to the remote application.
 
 - B_EVENT_ACTIVATED
 The bchannel beomes active.
 
-- B_EVENT_DEACTIVATE
+- B_EVENT_DROP
 The bchannel is not required by Port class anymore
 
 - B_EVENT_DEACTIVATED
 The bchannel becomes inactive.
 
+- B_EVENT_EXPORTED
+The bchannel is now used by remote application.
+
+- B_EVENT_IMPORTED
+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.
 
 */
@@ -608,36 +631,106 @@ 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)
+void bchannel_event(struct mISDNport *mISDNport, int i, int event, unsigned long to_remote)
 {
+       class PmISDN *b_port = mISDNport->b_port[i];
        int state = mISDNport->b_state[i];
+       unsigned long remote = mISDNport->b_remote[i];
+       unsigned long addr = mISDNport->b_addr[i];
 
        switch(event)
        {
-               case B_EVENT_ACTIVATE:
+               case B_EVENT_USE:
                /* port must be linked in order to allow activation */
-               if (!mISDNport->b_port[i])
+               if (!b_port)
                        FATAL("bchannel must be linked to a Port class\n");
                switch(state)
                {
                        case B_STATE_IDLE:
-                       /* create stack and send activation request */
-                       if (_bchannel_create(mISDNport, i))
+                       if (remote)
+                               PDEBUG(DEBUG_BCHANNEL, "idle channels don't have remote link.\n");
+                       if (to_remote)
                        {
-                               _bchannel_activate(mISDNport, i, 1);
-                               state = B_STATE_ACTIVATING;
+                               /* export bchannel */
+                               mISDNport->b_remote[i] = remote = to_remote;
+                               
+                               message_bchannel_to_join(remote, 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;
+                       } else
+                       {
+                               /* create stack and send activation request */
+                               if (_bchannel_create(mISDNport, i))
+                               {
+                                       _bchannel_activate(mISDNport, i, 1);
+                                       state = B_STATE_ACTIVATING;
+                               }
                        }
                        break;
 
                        case B_STATE_ACTIVATING:
+                       case B_STATE_EXPORTING:
+                       /* do nothing, because it is already activating */
+                       break;
+
+                       case B_STATE_DEACTIVATING:
+                       case B_STATE_IMPORTING:
+                       /* do nothing, because we must wait until we can reactivate */
+                       break;
+
+                       default:
+                       /* problems that might ocurr:
+                        * B_EVENT_USE is received when channel already in use.
+                        * bchannel exported, but not freed by other port
+                        */
+                       PERROR("Illegal event %d at state %d, please correct.\n", event, state);
+               }
+               break;
+
+               case B_EVENT_EXPORTREQUEST:
+               /* special case where the bchannel is requested by remote */
+               if (remote)
+               {
+                       PERROR("channel for join %d already exported to join %d, please correct.\n", to_remote, remote);
+               }
+               mISDNport->b_remote[i] = remote = to_remote;
+               switch(state)
+               {
+                       case B_STATE_IDLE:
+                       
+                       /* export bchannel */
+                       message_bchannel_to_join(remote, 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;
+                       break;
+
+                       case B_STATE_ACTIVATING:
+                       case B_STATE_EXPORTING:
                        /* do nothing, because it is already activating */
                        break;
 
                        case B_STATE_DEACTIVATING:
+                       case B_STATE_IMPORTING:
                        /* do nothing, because we must wait until we can reactivate */
                        break;
 
+                       case B_STATE_ACTIVE:
+                       /* bchannel is active, so we deactivate */
+                       _bchannel_activate(mISDNport, i, 0);
+                       state = B_STATE_DEACTIVATING;
+                       break;
+
                        default:
+                       /* problems that might ocurr:
+                        * ... when channel already in use.
+                        * bchannel exported, but not freed by other port
+                        */
                        PERROR("Illegal event %d at state %d, please correct.\n", event, state);
                }
                break;
@@ -646,14 +739,14 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event)
                switch(state)
                {
                        case B_STATE_ACTIVATING:
-                       if (mISDNport->b_port[i])
+                       if (b_port && !remote)
                        {
                                /* bchannel is active and used by Port class, so we configure bchannel */
                                _bchannel_configure(mISDNport, i);
                                state = B_STATE_ACTIVE;
                        } else
                        {
-                               /* bchannel is active, but not used anymore (or has wrong stack config), so we deactivate */
+                               /* bchannel is active, but exported OR not used anymore (or has wrong stack config), so we deactivate */
                                _bchannel_activate(mISDNport, i, 0);
                                state = B_STATE_DEACTIVATING;
                        }
@@ -664,9 +757,35 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event)
                }
                break;
 
-               case B_EVENT_DEACTIVATE:
-               if (!mISDNport->b_port[i])
+               case B_EVENT_EXPORTED:
+               switch(state)
+               {
+                       case B_STATE_EXPORTING:
+                       if (b_port && remote && to_remote==remote)
+                       {
+                               /* 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);
+                               chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
+                               add_trace("type", NULL, "remove");
+                               add_trace("stack", "address", "%x", addr);
+                               end_trace();
+                               state = B_STATE_IMPORTING;
+                       }
+                       break;
+
+                       default:
+                       PERROR("Illegal event %d at state %d, please correct.\n", event, state);
+               }
+               break;
+
+               case B_EVENT_DROP:
+               if (!b_port)
                        FATAL("bchannel must be linked to a Port class\n");
+               mISDNport->b_remote[i] = 0;
                switch(state)
                {
                        case B_STATE_IDLE:
@@ -674,6 +793,7 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event)
                        break;
 
                        case B_STATE_ACTIVATING:
+                       case B_STATE_EXPORTING:
                        /* do nothing because we must wait until bchanenl is active before deactivating */
                        break;
 
@@ -683,7 +803,18 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event)
                        state = B_STATE_DEACTIVATING;
                        break;
 
+                       case B_STATE_REMOTE:
+                       /* bchannel is exported, so we re-import */
+                       message_bchannel_to_join(remote, 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);
+                       end_trace();
+                       state = B_STATE_IMPORTING;
+                       break;
+
                        case B_STATE_DEACTIVATING:
+                       case B_STATE_IMPORTING:
                        /* we may have taken an already deactivating bchannel, but do not require it anymore, so we do nothing */
                        break;
 
@@ -702,13 +833,24 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event)
                        case B_STATE_DEACTIVATING:
                        _bchannel_destroy(mISDNport, i);
                        state = B_STATE_IDLE;
-                       if (mISDNport->b_port[i])
+                       if (b_port)
                        {
-                               /* bchannel is now deactivate, but is requied by Port class, so we reactivate */
-                               if (_bchannel_create(mISDNport, i))
+                               /* bchannel is now deactivate, but is requied by Port class, so we reactivate / export */
+                               if (remote)
                                {
-                                       _bchannel_activate(mISDNport, i, 1);
-                                       state = B_STATE_ACTIVATING;
+                                       message_bchannel_to_join(remote, 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;
+                               } else
+                               {
+                                       if (_bchannel_create(mISDNport, i))
+                                       {
+                                               _bchannel_activate(mISDNport, i, 1);
+                                               state = B_STATE_ACTIVATING;
+                                       }
                                }
                        }
                        break;
@@ -718,6 +860,39 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event)
                }
                break;
 
+               case B_EVENT_IMPORTED:
+               switch(state)
+               {
+                       case B_STATE_IMPORTING:
+                       state = B_STATE_IDLE;
+                       if (b_port)
+                       {
+                               /* bchannel is now imported, but is requied by Port class, so we reactivate / export */
+                               if (remote)
+                               {
+                                       message_bchannel_to_join(remote, 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;
+                               } else
+                               {
+                                       if (_bchannel_create(mISDNport, i))
+                                       {
+                                               _bchannel_activate(mISDNport, i, 1);
+                                               state = B_STATE_ACTIVATING;
+                                       }
+                               }
+                       }
+                       break;
+
+                       default:
+                       /* ignore, because not assigned */
+                       ;
+               }
+               break;
+
                default:
                PERROR("Illegal event %d, please correct.\n", event);
        }
@@ -792,6 +967,7 @@ 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;
@@ -827,13 +1003,98 @@ 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_DEACTIVATE);
+               bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_DROP, 0);
        p_m_mISDNport->b_port[p_m_b_index] = NULL;
+       p_m_mISDNport->b_remote[p_m_b_index] = 0;
        p_m_b_index = -1;
        p_m_b_channel = 0;
        p_m_b_exclusive = 0;
 }
 
+/* process bchannel export/import message from join */
+void message_bchannel_from_join(class JoinRemote *joinremote, int type, unsigned long addr)
+{
+       class Endpoint *epoint;
+       class Port *port;
+       class PmISDN *isdnport;
+       struct mISDNport *mISDNport;
+       int i, ii;
+
+       switch(type)
+       {
+               case BCHANNEL_REQUEST:
+               /* find the port object for the join object ref */
+               if (!(epoint = find_epoint_id(joinremote->j_epoint_id)))
+               {
+                       PDEBUG(DEBUG_BCHANNEL, "join %d has no endpoint (anymore)\n", joinremote->j_serial);
+                       return;
+               }
+               if (!epoint->ep_portlist)
+               {
+                       PDEBUG(DEBUG_BCHANNEL, "join %d has no port (anymore in portlist)\n", joinremote->j_serial);
+                       return;
+               }
+               if (epoint->ep_portlist->next)
+               {
+                       PERROR("join %d has enpoint %d with more than one port. this shall not happen to remote joins.\n", joinremote->j_serial, epoint->ep_serial);
+               }
+               if (!(port = find_port_id(epoint->ep_portlist->port_id)))
+               {
+                       PDEBUG(DEBUG_BCHANNEL, "join %d has no port (anymore as object)\n", joinremote->j_serial);
+                       return;
+               }
+               if (!((port->p_type&PORT_CLASS_MASK) != PORT_CLASS_mISDN))
+               {
+                       PERROR("join %d has port %d not of mISDN type. This shall not happen.\n", joinremote->j_serial, port->p_serial);
+               }
+               isdnport = (class PmISDN *)port;
+
+               /* assign */
+               if (isdnport->p_m_exportremote)
+               {
+                       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);
+               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);
+               end_trace();
+               break;
+
+               case BCHANNEL_ASSIGN_ACK:
+               case BCHANNEL_REMOVE_ACK:
+               /* find mISDNport for stack ID */
+               mISDNport = mISDNport_first;
+               while(mISDNport)
+               {
+                       i = 0;
+                       ii = mISDNport->b_num;
+                       while(i < ii)
+                       {
+                               if (mISDNport->b_addr[i] == addr)
+                                       break;
+                               i++;
+                       }
+                       if (i != ii)
+                               break;
+                       mISDNport = mISDNport->next;
+               }
+               /* 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);
+               end_trace();
+               break;
+               default:
+               PERROR("received wrong bchannel message type %d from remote\n", type);
+       }
+}
+
 
 /*
  * handler
@@ -1815,7 +2076,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);
+                       bchannel_event(mISDNport, i, B_EVENT_ACTIVATED, 0);
                        break;
 
                        case PH_DEACTIVATE | INDICATION:
@@ -1835,7 +2096,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);
+                       bchannel_event(mISDNport, i, B_EVENT_DEACTIVATED, 0);
                        break;
 
                        default:
diff --git a/mISDN.h b/mISDN.h
index db1a8cb..90ec032 100644 (file)
--- a/mISDN.h
+++ b/mISDN.h
@@ -9,20 +9,6 @@
 **                                                                           **
 \*****************************************************************************/ 
 
-enum {
-       B_STATE_IDLE,
-       B_STATE_ACTIVATING,
-       B_STATE_ACTIVE,
-       B_STATE_DEACTIVATING,
-};
-
-enum {
-       B_EVENT_ACTIVATE,
-       B_EVENT_ACTIVATED,
-       B_EVENT_DEACTIVATE,
-       B_EVENT_DEACTIVATED,
-};
-
 #define FROMUP_BUFFER_SIZE 1024
 #define FROMUP_BUFFER_MASK 1023
 
@@ -53,10 +39,11 @@ struct mISDNport {
        int d_stid;
        int b_num; /* number of bchannels */
        int b_reserved; /* number of bchannels reserved or in use */
-       class PmISDN *b_port[128]; /* maximum number of ports shall be 128 due to S0 / E1 / special E1 */
+       class PmISDN *b_port[128]; /* bchannel assigned to port object */
        int b_stid[128];
-       int b_addr[128];
-       int b_state[128]; /* state 0 = IDLE */
+       unsigned long b_addr[128];
+       int b_state[128]; /* statemachine, 0 = IDLE */
+       unsigned long b_remote[128]; /* if remote application requires bchannel */
        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 */
@@ -96,7 +83,8 @@ 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);
+void bchannel_event(struct mISDNport *mISDNport, int i, int event, unsigned long to_remote);
+void message_bchannel_from_join(class JoinRemote *joinremote, int type, unsigned long addr);
 
 
 /* mISDN port classes */
@@ -158,6 +146,7 @@ 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 */
 
        int seize_bchannel(int channel, int exclusive); /* requests / reserves / links bchannels, but does not open it! */
        void drop_bchannel(void);
index d60c1b3..422ada1 100644 (file)
--- a/message.h
+++ b/message.h
@@ -125,6 +125,33 @@ enum { /* isdnsignal */
        mISDNSIGNAL_DELAY,              /* use delay or adaptive jitter */
 };
 
+enum { /* bchannel assignment */
+       BCHANNEL_REQUEST,               /* application requests bchannel */
+       BCHANNEL_ASSIGN,                /* bchannel assigned by LCR */
+       BCHANNEL_ASSIGN_ACK,            /* application acknowledges */
+       BCHANNEL_REMOVE,                /* bchannel removed by LCR */
+       BCHANNEL_REMOVE_ACK,            /* application acknowledges */
+};
+enum {
+       B_STATE_IDLE,           /* not open */
+       B_STATE_ACTIVATING,     /* DL_ESTABLISH sent */
+       B_STATE_ACTIVE,         /* channel active */
+       B_STATE_DEACTIVATING,   /* DL_RELEASE sent */
+       B_STATE_EXPORTING,      /* BCHANNEL_ASSIGN sent */
+       B_STATE_REMOTE,         /* bchannel assigned to remote application */
+       B_STATE_IMPORTING,      /* BCHANNEL_REMOVE sent */
+};
+enum {
+       B_EVENT_USE,            /* activate/export bchannel */
+       B_EVENT_EXPORTREQUEST,  /* remote app requests bchannel */
+       B_EVENT_ACTIVATED,      /* DL_ESTABLISH received */
+       B_EVENT_DROP,           /* deactivate/re-import bchannel */
+       B_EVENT_DEACTIVATED,    /* DL_RELEASE received */
+       B_EVENT_EXPORTED,       /* BCHANNEL_ASSIGN received */
+       B_EVENT_IMPORTED,       /* BCHANNEL_REMOVE received */
+};
+
+
 /* call-info structure CALLER */
 struct caller_info {
        char id[32];                    /* id of caller (user number) */
@@ -279,6 +306,7 @@ struct param_hello {
 };
 
 struct param_bchannel {
+       int type; /* BCHANNEL_* */
        unsigned long addr; /* bchannel stack address */
 };
 
@@ -359,8 +387,7 @@ enum { /* messages between entities */
        MESSAGE_VBOX_TONE,      /* set answering VBOX tone */
        MESSAGE_TONE_COUNTER,   /* tone counter (for VBOX tone use) */
        MESSAGE_TONE_EOF,       /* tone is end of file */
-       MESSAGE_BCHANNEL,       /* request/assign bchannel */
-       MESSAGE_BCHANNEL_FREE,  /* requests/assigns bchannel to be free */
+       MESSAGE_BCHANNEL,       /* request/assign/remove bchannel */
        MESSAGE_HELLO,          /* hello message for remote application */
        MESSAGE_NEWREF,         /* special message to create and inform ref */
 };
index a78bba4..0c770a3 100644 (file)
@@ -159,3 +159,34 @@ the endpoint may receive MESSAGE_RELEASE from a call but may NOT send it
 to the port. the port MUST get a MESSAGE_DISCONNECT instead. 
  
 
+REMOTE APPLICATION PROCEDURE
+----------------------------
+
+MESSAGE_NEWREF
+- is sent before outgoing setup may be sent
+- is received before outgoing setup may be sent
+- is received before incoming call
+
+MESSAGE_BCHANNEL
+- type BCHANNEL_REQUEST is sent to get the bchannel stack
+  the ref is required to find the corresponding port class
+- type BCHANNEL_ASSIGN is received, if channel is available, ACK must be sent
+  the ref is given with the bchannel stack. 
+- type BCHANNEL_ASSIGN_ACK must be sent to acknowledge channel
+  the ref is 0, the stack address must be set to find corresponding channel
+- type BCHANNEL_REMOVE is received, if channel is not available anymore
+  the stack must then be release, the ACK must be sent.
+  the ref is given with the bchannel stack.
+- type BCHANNEL_REMOVE_ACK must be sent after releasing stack.
+  the ref is 0, the stack address must be set to find corresponding channel
+
+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.
+
+
+