Data-Over-Voice
[lcr.git] / dss1.cpp
index 6a718ab..43452bb 100644 (file)
--- a/dss1.cpp
+++ b/dss1.cpp
@@ -16,6 +16,7 @@
 extern "C" {
 }
 #include <mISDN/q931.h>
+#include <mISDN/suppserv.h>
 #ifdef OLD_MT_ASSIGN
 extern unsigned int mt_assign_pid;
 #endif
@@ -27,7 +28,7 @@ static int delete_event(struct lcr_work *work, void *instance, int index);
 /*
  * constructor
  */
-Pdss1::Pdss1(int type, struct mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive, int mode) : PmISDN(type, mISDNport, portname, settings, channel, exclusive, mode)
+Pdss1::Pdss1(int type, struct mISDNport *mISDNport, char *portname, struct port_settings *settings, struct interface *interface, int channel, int exclusive, int mode) : PmISDN(type, mISDNport, portname, settings, interface, channel, exclusive, mode)
 {
        p_callerinfo.itype = (mISDNport->ifport->interface->extension)?INFO_ITYPE_ISDN_EXTENSION:INFO_ITYPE_ISDN;
        p_m_d_ntmode = mISDNport->ntmode;
@@ -1641,21 +1642,50 @@ void Pdss1::resume_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
 /* CC_FACILITY INDICATION */
 void Pdss1::facility_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
 {
-       unsigned char facil[256];
-       int facil_len;
+       unsigned char fac_ie[256];
+       struct asn1_parm fac;
+       int fac_len;
        struct lcr_msg *message;
 
        l1l2l3_trace_header(p_m_mISDNport, this, L3_FACILITY_IND, DIRECTION_IN);
-       dec_ie_facility(l3m, facil, &facil_len);
+       dec_ie_facility(l3m, fac_ie + 1, &fac_len);
+       fac_ie[0] = fac_len;
        end_trace();
 
        /* facility */
-       if (facil_len<=0)
+       if (fac_len<=0)
                return;
 
+       decodeFac(fac_ie, &fac);
+       switch (fac.comp) {
+       case CompInvoke:
+               switch(fac.u.inv.operationValue) {
+                       case Fac_Begin3PTY:
+                       message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_3PTY);
+                       message->param.threepty.begin = 1;
+                       message->param.threepty.invoke = 1;
+                       message->param.threepty.invoke_id = fac.u.inv.invokeId;
+                       message_put(message);
+                       return;
+
+                       case Fac_End3PTY:
+                       message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_3PTY);
+                       message->param.threepty.end = 1;
+                       message->param.threepty.invoke = 1;
+                       message->param.threepty.invoke_id = fac.u.inv.invokeId;
+                       message_put(message);
+                       return;
+               default:
+                       ;
+               }
+               break;
+       default:
+               ;
+       }
+
        message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_FACILITY);
-       message->param.facilityinfo.len = facil_len;
-       memcpy(message->param.facilityinfo.data, facil, facil_len);
+       message->param.facilityinfo.len = fac_len;
+       memcpy(message->param.facilityinfo.data, fac_ie + 1, fac_len);
        message_put(message);
 }
 
@@ -1973,6 +2003,7 @@ void Pdss1::message_setup(unsigned int epoint_id, int message_id, union paramete
        /* screen outgoing caller id */
        do_screen(1, p_callerinfo.id, sizeof(p_callerinfo.id), &p_callerinfo.ntype, &p_callerinfo.present, p_m_mISDNport->ifport->interface->name);
        do_screen(1, p_callerinfo.id2, sizeof(p_callerinfo.id2), &p_callerinfo.ntype2, &p_callerinfo.present2, p_m_mISDNport->ifport->interface->name);
+       do_screen(1, p_redirinfo.id, sizeof(p_redirinfo.id), &p_redirinfo.ntype, &p_redirinfo.present, p_m_mISDNport->ifport->interface->name);
 
        /* only display at connect state: this case happens if endpoint is in connected mode */
        if (p_state==PORT_STATE_CONNECT) {
@@ -2283,6 +2314,40 @@ void Pdss1::message_facility(unsigned int epoint_id, int message_id, union param
        p_m_mISDNport->ml3->to_layer3(p_m_mISDNport->ml3, MT_FACILITY, p_m_d_l3id, l3m);
 }
 
+/* MESSAGE_3PTY */
+void Pdss1::message_3pty(unsigned int epoint_id, int message_id, union parameter *param)
+{
+       l3_msg *l3m;
+       unsigned char fac_ie[256];
+       struct asn1_parm fac;
+
+       /* encode 3PTY facility */
+       memset(&fac, 0, sizeof(fac));
+       fac.Valid = 1;
+       if (param->threepty.result) {
+               fac.comp = CompReturnResult;
+               fac.u.retResult.invokeId = param->threepty.invoke_id;
+               fac.u.retResult.operationValuePresent = 1;
+               if (param->threepty.begin)
+                       fac.u.retResult.operationValue = Fac_Begin3PTY;
+               if (param->threepty.end)
+                       fac.u.retResult.operationValue = Fac_End3PTY;
+       }
+       if (param->threepty.error) {
+               fac.comp = CompReturnError;
+               fac.u.retError.invokeId = param->threepty.invoke_id;
+               fac.u.retError.errorValue = FacError_Gen_InvalidCallState;
+       }
+       encodeFac(fac_ie, &fac);
+
+       /* sending facility */
+       l3m = create_l3msg();
+       l1l2l3_trace_header(p_m_mISDNport, this, L3_FACILITY_REQ, DIRECTION_OUT);
+       enc_ie_facility(l3m, fac_ie + 2, fac_ie[1]);
+       end_trace();
+       p_m_mISDNport->ml3->to_layer3(p_m_mISDNport->ml3, MT_FACILITY, p_m_d_l3id, l3m);
+}
+
 /* MESSAGE_NOTIFY */
 void Pdss1::message_notify(unsigned int epoint_id, int message_id, union parameter *param)
 {
@@ -2468,7 +2533,6 @@ void Pdss1::message_connect(unsigned int epoint_id, int message_id, union parame
 {
        l3_msg *l3m;
        int type, plan, present, screen;
-       class Endpoint *epoint;
        time_t current_time;
 
        /* NT-MODE in setup state we must send PROCEEDING first */
@@ -2488,18 +2552,7 @@ void Pdss1::message_connect(unsigned int epoint_id, int message_id, union parame
        /* screen outgoing caller id */
        do_screen(1, p_connectinfo.id, sizeof(p_connectinfo.id), &p_connectinfo.ntype, &p_connectinfo.present, p_m_mISDNport->ifport->interface->name);
 
-       /* only display at connect state */
-       if (p_state == PORT_STATE_CONNECT)
-       if (p_connectinfo.display[0]) {
-               /* sending information */
-               l3m = create_l3msg();
-               l1l2l3_trace_header(p_m_mISDNport, this, L3_INFORMATION_REQ, DIRECTION_OUT);
-               if (p_m_d_ntmode || p_m_d_tespecial)
-                       enc_ie_display(l3m, (unsigned char *)p_connectinfo.display);
-               end_trace();
-               p_m_mISDNport->ml3->to_layer3(p_m_mISDNport->ml3, MT_INFORMATION, p_m_d_l3id, l3m);
-               return;
-       }
+       set_display(p_connectinfo.display);
 
        if (p_state!=PORT_STATE_IN_SETUP && p_state!=PORT_STATE_IN_OVERLAP && p_state!=PORT_STATE_IN_PROCEEDING && p_state!=PORT_STATE_IN_ALERTING) {
                /* connect command only possible in setup, proceeding or alerting state */
@@ -2563,7 +2616,6 @@ void Pdss1::message_connect(unsigned int epoint_id, int message_id, union parame
 //             enc_facility_centrex(&connect->FACILITY, dmsg, (unsigned char *)p_connectinfo.name, 0);
        /* date & time */
        if (p_m_d_ntmode || p_m_d_tespecial) {
-               epoint = find_epoint_id(epoint_id);
                time(&current_time);
                enc_ie_date(l3m, current_time, p_settings.no_seconds);
        }
@@ -2651,7 +2703,6 @@ if (/*     ||*/ p_state==PORT_STATE_OUT_SETUP) {
 void Pdss1::message_release(unsigned int epoint_id, int message_id, union parameter *param)
 {
        l3_msg *l3m;
-       class Endpoint *epoint;
        char *p = NULL;
 
        /*
@@ -2731,7 +2782,6 @@ wirklich erst proceeding?:
        /* send cause */
        enc_ie_cause(l3m, (p_m_mISDNport->locally && param->disconnectinfo.location==LOCATION_PRIVATE_LOCAL)?LOCATION_PRIVATE_LOCAL:param->disconnectinfo.location, param->disconnectinfo.cause);
        /* send display */
-       epoint = find_epoint_id(epoint_id);
        if (param->disconnectinfo.display[0])
                p = param->disconnectinfo.display;
        if (p) if (*p && (p_m_d_ntmode || p_m_d_tespecial))
@@ -2805,6 +2855,10 @@ int Pdss1::message_epoint(unsigned int epoint_id, int message_id, union paramete
                message_facility(epoint_id, message_id, param);
                break;
 
+               case MESSAGE_3PTY: /* begin result message */
+               message_3pty(epoint_id, message_id, param);
+               break;
+
                case MESSAGE_OVERLAP: /* more information is needed */
                if (p_state!=PORT_STATE_IN_SETUP) {
                        break;
@@ -2974,7 +3028,7 @@ int stack2manager(struct mISDNport *mISDNport, unsigned int cmd, unsigned int pi
                case MT_SETUP:
                /* creating port object, transparent until setup with hdlc */
                SPRINT(name, "%s-%d-in", mISDNport->ifport->interface->name, mISDNport->portnum);
-               if (!(pdss1 = new Pdss1(PORT_TYPE_DSS1_NT_IN, mISDNport, name, NULL, 0, 0, B_MODE_TRANSPARENT)))
+               if (!(pdss1 = new Pdss1(PORT_TYPE_DSS1_NT_IN, mISDNport, name, NULL, mISDNport->ifport->interface, 0, 0, B_MODE_TRANSPARENT)))
 
                        FATAL("Cannot create Port instance.\n");
                pdss1->message_isdn(cmd, pid, l3m);
@@ -2983,7 +3037,7 @@ int stack2manager(struct mISDNport *mISDNport, unsigned int cmd, unsigned int pi
                case MT_RESUME:
                /* creating port object, transparent until setup with hdlc */
                SPRINT(name, "%s-%d-in", mISDNport->ifport->interface->name, mISDNport->portnum);
-               if (!(pdss1 = new Pdss1(PORT_TYPE_DSS1_NT_IN, mISDNport, name, NULL, 0, 0, B_MODE_TRANSPARENT)))
+               if (!(pdss1 = new Pdss1(PORT_TYPE_DSS1_NT_IN, mISDNport, name, NULL, mISDNport->ifport->interface, 0, 0, B_MODE_TRANSPARENT)))
                        FATAL("Cannot create Port instance.\n");
                pdss1->message_isdn(cmd, pid, l3m);
                break;
@@ -3023,6 +3077,23 @@ int stack2manager(struct mISDNport *mISDNport, unsigned int cmd, unsigned int pi
        return(0);
 }
 
+void Pdss1::set_display(const char *text)
+{
+       l3_msg *l3m;
+
+       /* only display at connect state */
+       if (p_state == PORT_STATE_CONNECT)
+       if (text[0]) {
+               /* sending information */
+               l3m = create_l3msg();
+               l1l2l3_trace_header(p_m_mISDNport, this, L3_INFORMATION_REQ, DIRECTION_OUT);
+               if (p_m_d_ntmode || p_m_d_tespecial)
+                       enc_ie_display(l3m, (unsigned char *)text);
+               end_trace();
+               p_m_mISDNport->ml3->to_layer3(p_m_mISDNport->ml3, MT_INFORMATION, p_m_d_l3id, l3m);
+               return;
+       }
+}