SIP: Fix incoming re-invite
[lcr.git] / gsm.cpp
diff --git a/gsm.cpp b/gsm.cpp
index 5ed0f89..9ab9650 100644 (file)
--- a/gsm.cpp
+++ b/gsm.cpp
@@ -290,6 +290,15 @@ void Pgsm::frame_receive(void *arg)
                return;
 
        switch (frame->msg_type) {
+       case ANALOG_8000HZ:
+               if (p_g_media_type != MEDIA_TYPE_ANALOG) {
+                       PERROR("'Analog' frame, but current media type mismatches.\n");
+                       return;
+               }
+               for (i = 0; i < 160; i++) {
+                       data[i] = audio_s16_to_law[((int16_t *)frame->data)[i] & 0xffff];
+               }
+               break;
        case GSM_TCHF_FRAME:
                if (p_g_media_type != MEDIA_TYPE_GSM) {
                        PERROR("FR frame, but current media type mismatches.\n");
@@ -426,7 +435,6 @@ int Pgsm::bridge_rx(unsigned char *data, int len)
 int Pgsm::audio_send(unsigned char *data, int len)
 {
        unsigned char frame[33];
-       int ret;
 
        /* record data */
        if (p_record)
@@ -450,6 +458,9 @@ int Pgsm::audio_send(unsigned char *data, int len)
                p_g_rxpos = 0;
 
                switch (p_g_media_type) {
+               case MEDIA_TYPE_ANALOG:
+                       frame_send(p_g_rxdata, 320, ANALOG_8000HZ);
+                       break;
                case MEDIA_TYPE_GSM:
                        if (!p_g_fr_encoder) {
                                PERROR("FR frame, but encoder not created.\n");
@@ -494,6 +505,7 @@ int Pgsm::audio_send(unsigned char *data, int len)
                        }
 #ifdef WITH_GSMAMR
                        /* encode data (prefix a length byte) */
+                       int ret;
                        ret = gsm_amr_encode(p_g_amr_encoder, p_g_rxdata, frame + 1, p_g_amr_cmr);
                        frame[0] = ret;
                        frame_send(frame, ret + 1, GSM_TCH_FRAME_AMR);
@@ -655,7 +667,20 @@ void Pgsm::setup_cnf(unsigned int msg_type, unsigned int callref, struct gsm_mnc
        SCPY(p_connectinfo.imsi, mncc->imsi);
        p_connectinfo.present = INFO_PRESENT_ALLOWED;
        p_connectinfo.screen = INFO_SCREEN_NETWORK;
-       p_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
+       switch (mncc->connected.type) {
+               case 0x1:
+               p_connectinfo.ntype = INFO_NTYPE_INTERNATIONAL;
+               break;
+               case 0x2:
+               p_connectinfo.ntype = INFO_NTYPE_NATIONAL;
+               break;
+               case 0x4:
+               p_connectinfo.ntype = INFO_NTYPE_SUBSCRIBER;
+               break;
+               default:
+               p_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
+               break;
+       }
        SCPY(p_connectinfo.interface, p_interface_name);
 
        gsm_trace_header(p_interface_name, this, msg_type, DIRECTION_IN);
@@ -1254,6 +1279,9 @@ static int mncc_send(struct lcr_gsm *lcr_gsm, int msg_type, void *data)
 
        /* FIXME: the caller should provide this */
        switch (msg_type) {
+       case ANALOG_8000HZ:
+               len = sizeof(struct gsm_data_frame) + 320;
+               break;
        case GSM_TCHF_FRAME:
                len = sizeof(struct gsm_data_frame) + 33;
                break;
@@ -1340,6 +1368,9 @@ static int mncc_fd_read(struct lcr_fd *lfd, void *inst, int idx)
        static char buf[sizeof(struct gsm_mncc)+1024];
        struct gsm_mncc *mncc_prim = (struct gsm_mncc *) buf;
        struct gsm_mncc_hello *hello = (struct gsm_mncc_hello *) buf;
+       class Port *port;
+       class Pgsm *pgsm = NULL;
+       unsigned int callref;
 
        memset(buf, 0, sizeof(buf));
        rc = recv(lfd->fd, buf, sizeof(buf), 0);
@@ -1387,15 +1418,31 @@ static int mncc_fd_read(struct lcr_fd *lfd, void *inst, int idx)
                break;
        }
 
+       /* Find port object */
+       callref = mncc_prim->callref;
+       port = port_first;
+       while(port) {
+               if ((port->p_type & PORT_CLASS_MASK) == PORT_CLASS_GSM) {
+                       pgsm = (class Pgsm *)port;
+                       if (pgsm->p_g_lcr_gsm == lcr_gsm && pgsm->p_g_callref == callref)
+                               break;
+               }
+               port = port->next;
+       }
+
        /* Hand the MNCC message into LCR */
        switch (lcr_gsm->type) {
 #ifdef WITH_GSM_BS
        case LCR_GSM_TYPE_NETWORK:
-               return message_bsc(lcr_gsm, mncc_prim->msg_type, mncc_prim);
+               if (port && (port->p_type & PORT_CLASS_GSM_MASK) != PORT_CLASS_GSM_BS)
+                       FATAL("Port is set and bound to network socket, but is not of network type, please fix");
+               return message_bsc((class Pgsm_bs *)port, lcr_gsm, mncc_prim->msg_type, mncc_prim);
 #endif
 #ifdef WITH_GSM_MS
        case LCR_GSM_TYPE_MS:
-               return message_ms(lcr_gsm, mncc_prim->msg_type, mncc_prim);
+               if (port && (port->p_type & PORT_CLASS_GSM_MASK) != PORT_CLASS_GSM_MS)
+                       FATAL("Port is set and bound to mobile socket, but is not of mobile type, please fix");
+               return message_ms((class Pgsm_ms *)port, lcr_gsm, mncc_prim->msg_type, mncc_prim);
 #endif
        default:
                return 0;