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:
                                                        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);
                                                        } else
                                                        {
                                                                color(red);
-                                                               addstr("blk ");
+                                                               addstr("blocked ");
                                                        }
                                                        if (m[i].u.i.port[j])
                                                        {
                                                        }
                                                        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;
                                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;
                                /* 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;
 
        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");
                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);
        }
 
                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)
        {
        /* 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 */
        }
 
        /* send message */
-       ((class JoinRemote *)join)->message_remote(msg->ref, msg->type, &msg->param);
+       ((class JoinRemote *)join)->message_remote(msg->type, &msg->param);
 
        return(0);
 }
 
        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;
 
                port_resume(portlist, message_type, param);
                break;
 
+#if 0
                /* port assigns bchannel */
                /* 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;
                /* 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:
 
 
                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)
 {
  */
 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)
        {
 
        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;
        }
 
                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)
        {
        /* 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)
                {
                        /* 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)
        {
        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;
 
                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;
 
                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;
 
                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
                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;
 
                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)
                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;
 
                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
                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;
 
                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
                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;
 
                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;
 
                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;
 
                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;
 
                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: /* 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;
                /* 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;
                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)
                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;
 
                }
                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)
                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
                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);
                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
 
                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);
                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;
 
                end_trace();
                break;
 
+#if 0
                case MESSAGE_BCHANNEL:
                case MESSAGE_BCHANNEL:
-               case MESSAGE_BCHANNEL_FREE:
                trace_header("BCHANNEL", dir);
                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;
                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);
 
                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 */
                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)
        {
        } 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
                        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);
                }
 
                        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 */
                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)
        {
        } 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 */
                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' ***/
        } 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 */
                        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);
                }
                
                        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 */
                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);
 
        }
        return(0);
 
@@ -731,12 +731,12 @@ void Pdss1::setup_ind(unsigned long prim, unsigned long dinfo, void *data)
                p_m_delete = 1;
                return;
        }
                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");
 
        /* 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");
                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;
        }
                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;
 
        /* 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;
        }
                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)
 
        /* 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 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;
 {
        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 */
        *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)
 
        /* link to join or port */
        if (port_id)
index 460c0d7..a336beb 100644 (file)
@@ -22,7 +22,7 @@ struct port_list {
 class Endpoint
 {
        public:
 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 */
        ~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 */
        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)))
        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_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));
        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);
 }
        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()
 {
  */
 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;
 
 {
        struct message *message;
 
@@ -96,12 +96,22 @@ void JoinRemote::message_remote(unsigned long ref, int message_type, union param
        {
                class Endpoint          *epoint;
 
        {
                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");
                        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");
        }
 
                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);
        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);
        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;
        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_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;
 
        /* audio */
        p_m_load = 0;
@@ -472,7 +473,7 @@ failed:
 
 /*
  * subfunction for bchannel_event
 
 /*
  * subfunction for bchannel_event
- * activate request
+ * activate / deactivate request
  */
 static void _bchannel_activate(struct mISDNport *mISDNport, int i, int activate)
 {
  */
 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.
 
 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:
 
 
 A bchannel can have the following events:
 
-- B_EVENT_ACTIVATE
+- B_EVENT_USE
 A bchannel is required by a Port class.
 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_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.
 
 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.
 
 */
 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
  */
  * - 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];
        int state = mISDNport->b_state[i];
+       unsigned long remote = mISDNport->b_remote[i];
+       unsigned long addr = mISDNport->b_addr[i];
 
        switch(event)
        {
 
        switch(event)
        {
-               case B_EVENT_ACTIVATE:
+               case B_EVENT_USE:
                /* port must be linked in order to allow activation */
                /* 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:
                        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:
                        }
                        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:
                        /* 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;
 
                        /* 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:
                        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;
                        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:
                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 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;
                        }
                                _bchannel_activate(mISDNport, i, 0);
                                state = B_STATE_DEACTIVATING;
                        }
@@ -664,9 +757,35 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event)
                }
                break;
 
                }
                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");
                        FATAL("bchannel must be linked to a Port class\n");
+               mISDNport->b_remote[i] = 0;
                switch(state)
                {
                        case B_STATE_IDLE:
                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:
                        break;
 
                        case B_STATE_ACTIVATING:
+                       case B_STATE_EXPORTING:
                        /* do nothing because we must wait until bchanenl is active before deactivating */
                        break;
 
                        /* 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;
 
                        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_DEACTIVATING:
+                       case B_STATE_IMPORTING:
                        /* we may have taken an already deactivating bchannel, but do not require it anymore, so we do nothing */
                        break;
 
                        /* 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;
                        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;
                                }
                        }
                        break;
@@ -718,6 +860,39 @@ void bchannel_event(struct mISDNport *mISDNport, int i, int event)
                }
                break;
 
                }
                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);
        }
                default:
                PERROR("Illegal event %d, please correct.\n", event);
        }
@@ -792,6 +967,7 @@ seize:
 
        /* link Port */
        p_m_mISDNport->b_port[i] = this;
 
        /* 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;
        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)
        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_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;
 }
 
        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
 
 /*
  * 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;
                        }
                                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:
                        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;
                        }
                                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:
                        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
 
 #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 */
        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_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 */
        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);
 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 */
 
 
 /* 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 */
        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);
 
        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 */
 };
 
        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) */
 /* 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 {
 };
 
 struct param_bchannel {
+       int type; /* BCHANNEL_* */
        unsigned long addr; /* bchannel stack address */
 };
 
        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_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 */
 };
        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. 
  
 
 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.
+
+
+