]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
More PRI/SIP gateway stuff
authorAnthony Minessale <anthony.minessale@gmail.com>
Thu, 23 Feb 2006 22:41:08 +0000 (22:41 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Thu, 23 Feb 2006 22:41:08 +0000 (22:41 +0000)
**ATTENTION** you will need to libs/jrtplib/.complete ; make installall
to get it to compile on existing builds as the jrtplib required changes.

Added teletone DTMF to mod_wanpipe and rfc2933 DTMF to mod_exosip
Added temporary poor man's daemon
freeswitch -nc > /var/log/freeswitch.log

then it will await a HUP

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@659 d0543943-73ff-0310-b7d9-9358b9ac24b2

libs/jrtplib/src/jrtp4c.cpp
libs/jrtplib/src/jrtp4c.h
src/include/switch_types.h
src/include/switch_utils.h
src/mod/endpoints/mod_exosip/mod_exosip.c
src/mod/endpoints/mod_wanpipe/mod_wanpipe.c
src/switch.c
src/switch_utils.c

index cb227684985a8e1a01211078c92f95f3330af803..518a18ef42630133ea4b001d089f60518ed95b4a 100644 (file)
@@ -156,6 +156,11 @@ extern "C" {
                return jrtp4c->session->SendPacket(data, datalen, jrtp4c->payload, false, ts);
        }
 
+       int jrtp4c_write_payload(struct jrtp4c *jrtp4c, void *data, int datalen, int payload, uint32_t ts, uint32_t mseq)
+       {
+               return jrtp4c->session->SendPacket(data, datalen, payload, false, ts, mseq);
+       }
+
        uint32_t jrtp4c_start(struct jrtp4c *jrtp4c)
        {
                //jrtp4c->session->BeginDataAccess();
index f168892468410300e359addf3474188bfc75a30d..e4de89f9ea64016abe35e92da74621467f0cd6ca 100644 (file)
@@ -51,6 +51,7 @@ extern "C" {
        void jrtp4c_destroy(struct jrtp4c **jrtp4c);
        int jrtp4c_read(struct jrtp4c *jrtp4c, void *data, int datalen, int *payload_type);
        int jrtp4c_write(struct jrtp4c *jrtp4c, void *data, int datalen, uint32_t ts);
+       int jrtp4c_write_payload(struct jrtp4c *jrtp4c, void *data, int datalen, int payload, uint32_t ts, uint32_t mseq);
        uint32_t jrtp4c_start(struct jrtp4c *jrtp4c);
        uint32_t jrtp4c_get_ssrc(struct jrtp4c *jrtp4c);
        void jrtp4c_killread(struct jrtp4c *jrtp4c);
index af2c4f070b3e927d7a19f83c8b2164f01e17ca93..b89c4a88d8d8768dfee2eb273f1c0ac7a5bd2501 100644 (file)
@@ -44,6 +44,8 @@ extern "C" {
 #define SWITCH_RECCOMMENDED_BUFFER_SIZE 131072
 #define SWITCH_MAX_CODECS 30
 #define SWITCH_MAX_STATE_HANDLERS 30
+#define SWITCH_TRUE 1
+#define SWITCH_FALSE 0
 
 /*!
   \enum switch_ivr_option_t
index fd523dc3fad4b70d81924187089a065cc3bc5c6b..46fdb8fe64c841f5fbccd136e99c77040cfe65ce 100644 (file)
@@ -44,6 +44,8 @@ extern "C" {
 
 #include <switch.h>
 
+
+
 #ifndef snprintf
 #define snprintf apr_snprintf
 #endif
@@ -51,6 +53,34 @@ extern "C" {
 #define vsnprintf apr_vsnprintf
 #endif
 
+
+/*!
+  \brief Evaluate the truthfullness of a string expression
+  \param expr a string expression
+  \return true or false 
+*/
+#define switch_true(expr)\
+(expr && ( !strcasecmp(expr, "yes") ||\
+!strcasecmp(expr, "on") ||\
+!strcasecmp(expr, "true") ||\
+atoi(expr))) ? SWITCH_TRUE : SWITCH_FALSE
+
+
+
+/*!
+  \brief Return the RFC2833 character based on an event id
+  \param event the event id to convert
+  \return the character represented by the event or null for an invalid event
+*/
+SWITCH_DECLARE(char) switch_rfc2833_to_char(int event);
+
+/*!
+  \brief Return the RFC2833 event based on an key character
+  \param the charecter to encode
+  \return the event id for the specified character or -1 on an invalid input
+*/
+SWITCH_DECLARE(int) switch_char_to_rfc2833(char key);
+
 /*!
   \brief Duplicate a string 
 */
index 2dc793bce2863d5eaf114d8e184f7c039e98cc5e..fa5045ff3048d45c2ce9cefed3d6bb01d9878828 100644 (file)
@@ -43,6 +43,8 @@ static const char modname[] = "mod_exosip";
 
 static switch_memory_pool *module_pool;
 
+
+
 typedef enum {
        PFLAG_ANSWER = (1 << 0),
        PFLAG_HANGUP = (1 << 1),
@@ -85,6 +87,8 @@ static struct {
        switch_mutex_t *port_lock;
        int running;
        int codec_ms;
+       int supress_telephony_events;
+       int dtmf_duration;
 } globals;
 
 struct private_object {
@@ -100,6 +104,7 @@ struct private_object {
        int tid;
        int32_t timestamp_send;
        int32_t timestamp_recv;
+       int32_t timestamp_dtmf;
        int payload_num;
        struct jrtp4c *rtp_session;
        struct osip_rfc3264 *sdp_config;
@@ -111,7 +116,14 @@ struct private_object {
        int local_sdp_audio_port;
        char call_id[50];
        int ssrc;
+       char last_digit;
        switch_mutex_t *rtp_lock;
+       switch_queue_t *dtmf_queue;
+       char out_digit;
+       unsigned char out_digit_packet[4];
+       unsigned int out_digit_sofar;
+       unsigned int out_digit_dur;
+       unsigned int out_digit_seq;
 };
 
 
@@ -129,6 +141,10 @@ static int next_rtp_port(void)
        return port;
 }
 
+struct rfc2833_digit {
+       char digit;
+       int duration;
+};
 
 SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_dialplan, globals.dialplan)
 SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_codec_string, globals.codec_string)
@@ -148,7 +164,7 @@ static switch_status parse_sdp_media(sdp_media_t * media, char **dname, char **d
 static switch_status exosip_kill_channel(switch_core_session *session, int sig);
 static void activate_rtp(struct private_object *tech_pvt);
 static void deactivate_rtp(struct private_object *tech_pvt);
-static void sdp_add_rfc2833(struct osip_rfc3264 *cnf);
+static void sdp_add_rfc2833(struct osip_rfc3264 *cnf, int rate);
 
 static struct private_object *get_pvt_by_call_id(int id)
 {
@@ -282,11 +298,11 @@ static switch_status exosip_on_init(switch_core_session *session)
                                                         imp->samples_per_second);
                                        sdp_message_a_attribute_add(tech_pvt->local_sdp, 0, "rtpmap", osip_strdup(tmp));
                                        memset(tmp, 0, sizeof(tmp));
-                               }
+                               } 
                        }
                }
 
-               sdp_add_rfc2833(tech_pvt->sdp_config);
+               sdp_add_rfc2833(tech_pvt->sdp_config, 8000);
 
                /* Setup our INVITE */
                eXosip_lock();
@@ -517,11 +533,12 @@ static switch_status exosip_read_frame(switch_core_session *session, switch_fram
        }
 
        if (switch_test_flag(tech_pvt, TFLAG_IO)) {
+
+               
                if (!switch_test_flag(tech_pvt, TFLAG_RTP)) {
                        return SWITCH_STATUS_GENERR;
                }
 
-
                assert(tech_pvt->rtp_session != NULL);
                tech_pvt->read_frame.datalen = 0;
 
@@ -530,31 +547,24 @@ static switch_status exosip_read_frame(switch_core_session *session, switch_fram
                        tech_pvt->read_frame.datalen =
                                jrtp4c_read(tech_pvt->rtp_session, tech_pvt->read_frame.data, sizeof(tech_pvt->read_buf), &payload);
 
-
-                       
+                       /* RFC2833 ... TBD try harder to honor the duration etc.*/
                        if (payload == 101) {
-                               unsigned char *data;
-                               unsigned int event;
-                unsigned int event_end;
-                unsigned int duration;
-                               data = tech_pvt->read_frame.data;
-                               
-                               event = ntohl(*((unsigned int *)(data)));
-                event >>= 24;
-                event_end = ntohl(*((unsigned int *)(data)));
-                event_end <<= 8;
-                event_end >>= 24;
-                duration = ntohl(*((unsigned int *)(data)));
-                duration &= 0xFFFF;
-
-                               printf("DTMF %d %d %d\n", event, event_end, duration);
+                               unsigned char *packet = tech_pvt->read_frame.data;
+                               int end = packet[1]&0x80;
+                               int duration = (packet[2]<<8) + packet[3];
+                               char key = switch_rfc2833_to_char(packet[0]);
+
+                               if (duration && end && key != tech_pvt->last_digit) {
+                                       char digit_str[] = {key, 0};
+                                       switch_channel_queue_dtmf(channel, digit_str);
+                                       tech_pvt->last_digit = key;
+                               }
                        }
 
-                       if (payload != tech_pvt->payload_num) {
-                               printf("lets skip %d\n", payload);
+                       if (globals.supress_telephony_events && payload != tech_pvt->payload_num) {
                                continue;
                        }
-
+                       
                        if (tech_pvt->read_frame.datalen > 0) {
                                bytes = tech_pvt->read_codec.implementation->encoded_bytes_per_frame;
                                frames = (tech_pvt->read_frame.datalen / bytes);
@@ -568,14 +578,6 @@ static switch_status exosip_read_frame(switch_core_session *session, switch_fram
                        switch_yield(100);
                }
 
-               //tech_pvt->timestamp_recv += samples;
-
-
-               //printf("%s %s->%s recv %d bytes %d samples in %d frames taking up %d ms ts=%d\n", switch_channel_get_name(channel), tech_pvt->local_sdp_audio_ip, tech_pvt->local_sdp_audio_ip, tech_pvt->read_frame.datalen, samples, frames, ms, tech_pvt->timestamp_recv);
-
-
-               //switch_mutex_unlock(tech_pvt->rtp_lock);
-
        } else {
                memset(tech_pvt->read_buf, 0, 160);
                tech_pvt->read_frame.datalen = 160;
@@ -590,7 +592,6 @@ static switch_status exosip_read_frame(switch_core_session *session, switch_fram
 
        *frame = &tech_pvt->read_frame;
 
-
        return SWITCH_STATUS_SUCCESS;
 }
 
@@ -635,6 +636,60 @@ static switch_status exosip_write_frame(switch_core_session *session, switch_fra
        }
 
 
+       if (tech_pvt->out_digit_dur > 0) {
+               int x, ts, loops = 1, duration;
+
+               tech_pvt->out_digit_sofar += samples;
+
+               if (tech_pvt->out_digit_sofar >= tech_pvt->out_digit_dur) {
+                       duration = tech_pvt->out_digit_dur;
+                       tech_pvt->out_digit_packet[1] |= 0x80;
+                       tech_pvt->out_digit_dur = 0;
+                       loops = 3;
+               } else {
+                       duration = tech_pvt->out_digit_sofar;
+               }
+
+               ts = tech_pvt->timestamp_dtmf += samples;
+               tech_pvt->out_digit_packet[2] = (unsigned char) (duration >> 8);
+               tech_pvt->out_digit_packet[3] = (unsigned char) duration;
+               
+
+               for (x = 0; x < loops; x++) {
+                       jrtp4c_write_payload(tech_pvt->rtp_session, tech_pvt->out_digit_packet, 4, 101, ts, tech_pvt->out_digit_seq);
+                       printf("Send %s packet for [%c] ts=%d sofar=%d dur=%d\n", loops == 1 ? "middle" : "end", tech_pvt->out_digit, ts, 
+                                  tech_pvt->out_digit_sofar, duration);
+               }
+       }
+
+       if (!tech_pvt->out_digit_dur && tech_pvt->dtmf_queue && switch_queue_size(tech_pvt->dtmf_queue)) {
+               void *pop;
+
+               if (switch_queue_trypop(tech_pvt->dtmf_queue, &pop) == SWITCH_STATUS_SUCCESS) {
+                       int x, ts;
+                       struct rfc2833_digit *rdigit = pop;
+                       
+                       memset(tech_pvt->out_digit_packet, 0, 4);
+                       tech_pvt->out_digit_sofar = 0;
+                       tech_pvt->out_digit_dur = rdigit->duration;
+                       tech_pvt->out_digit = rdigit->digit;
+                       tech_pvt->out_digit_packet[0] = switch_char_to_rfc2833(rdigit->digit);
+                       tech_pvt->out_digit_packet[1] = 7;
+
+                       ts = tech_pvt->timestamp_dtmf += samples;
+                       tech_pvt->out_digit_seq++;
+                       for (x = 0; x < 3; x++) {
+                               jrtp4c_write_payload(tech_pvt->rtp_session, tech_pvt->out_digit_packet, 4, 101, ts, tech_pvt->out_digit_seq);
+                               printf("Send start packet for [%c] ts=%d sofar=%d dur=%d\n", tech_pvt->out_digit, ts, 
+                                          tech_pvt->out_digit_sofar, 0);
+                       }
+
+                       free(rdigit);
+               }
+       }
+
+
+
        //printf("%s %s->%s send %d bytes %d samples in %d frames taking up %d ms ts=%d\n", switch_channel_get_name(channel), tech_pvt->local_sdp_audio_ip, tech_pvt->remote_sdp_audio_ip, frame->datalen, samples, frames, ms, tech_pvt->timestamp_send);
 
 
@@ -699,7 +754,30 @@ static switch_status exosip_waitfor_write(switch_core_session *session, int ms,
 
 static switch_status exosip_send_dtmf(switch_core_session *session, char *digits)
 {
-       return SWITCH_STATUS_FALSE;
+       struct private_object *tech_pvt;
+       char *c;
+
+       tech_pvt = switch_core_session_get_private(session);
+    assert(tech_pvt != NULL);
+
+       if (!tech_pvt->dtmf_queue) {
+               switch_queue_create(&tech_pvt->dtmf_queue, 100, switch_core_session_get_pool(session));
+       }
+
+       for(c = digits; *c; c++) {
+               struct rfc2833_digit *rdigit;
+
+               if ((rdigit = malloc(sizeof(*rdigit)))) {
+                       memset(rdigit, 0, sizeof(*rdigit));
+                       rdigit->digit = *c;
+                       rdigit->duration = globals.dtmf_duration * (tech_pvt->read_codec.implementation->samples_per_second / 1000);
+                       switch_queue_push(tech_pvt->dtmf_queue, rdigit);
+               } else {
+                       return SWITCH_STATUS_MEMERR;
+               }
+       }
+
+       return SWITCH_STATUS_SUCCESS;
 }
 
 static switch_status exosip_receive_message(switch_core_session *session, switch_core_session_message *msg)
@@ -726,7 +804,6 @@ static switch_status exosip_receive_message(switch_core_session *session, switch
                                /* Transmit 183 Progress with SDP */
                                eXosip_lock();
                                eXosip_call_build_answer(tech_pvt->tid, 183, &progress);
-                               sdp_add_rfc2833(tech_pvt->sdp_config);
                                sdp_message_to_str(tech_pvt->local_sdp, &buf);
                                osip_message_set_body(progress, buf, strlen(buf));
                                osip_message_set_content_type(progress, "application/sdp");
@@ -831,7 +908,7 @@ static switch_status exosip_outgoing_channel(switch_core_session *session, switc
        return SWITCH_STATUS_GENERR;
 }
 
-#if 1
+
 SWITCH_MOD_DECLARE(switch_status) switch_module_shutdown(void)
 {
        if (globals.running) {
@@ -842,7 +919,7 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_shutdown(void)
        }
        return SWITCH_STATUS_SUCCESS;
 }
-#endif
+
 SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **interface, char *filename)
 {
        /* NOTE:  **interface is **_interface because the common lib redefines interface to struct in some situations */
@@ -859,15 +936,17 @@ SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_modul
        return SWITCH_STATUS_SUCCESS;
 }
 
-static void sdp_add_rfc2833(struct osip_rfc3264 *cnf)
+static void sdp_add_rfc2833(struct osip_rfc3264 *cnf, int rate)
 {
        sdp_media_t *med = NULL;
        sdp_attribute_t *attr = NULL;
-
+       char tmp[128];
+       
        sdp_media_init(&med);
        sdp_attribute_init(&attr);
        attr->a_att_field = osip_strdup("rtpmap");
-       attr->a_att_value = osip_strdup("101 telephony-event/8000");
+       snprintf(tmp, sizeof(tmp), "101 telephony-event/%d", rate);
+       attr->a_att_value = osip_strdup(tmp);
        osip_list_add(med->a_attributes, attr, -1);
        
 
@@ -876,6 +955,7 @@ static void sdp_add_rfc2833(struct osip_rfc3264 *cnf)
 
 }
 
+
 static switch_status exosip_create_call(eXosip_event_t * event)
 {
        switch_core_session *session;
@@ -956,7 +1036,7 @@ static switch_status exosip_create_call(eXosip_event_t * event)
                        int i;
                        static const switch_codec_implementation *imp;
 
-                       sdp_add_rfc2833(tech_pvt->sdp_config);
+
 
                        for (i = 0; i < num_codecs; i++) {
                                int x = 0;
@@ -967,6 +1047,8 @@ static switch_status exosip_create_call(eXosip_event_t * event)
                                }
                        }
                }
+               sdp_add_rfc2833(tech_pvt->sdp_config, 8000);
+
                osip_rfc3264_prepare_answer(tech_pvt->sdp_config, remote_sdp, local_sdp_str, 8192);
                sdp_message_init(&tech_pvt->local_sdp);
                sdp_message_parse(tech_pvt->local_sdp, local_sdp_str);
@@ -1377,6 +1459,7 @@ static int config_exosip(int reload)
 
        globals.rtp_start = 16384;
        globals.rtp_end = 32768;
+       globals.dtmf_duration = 100;
 
        while (switch_config_next_pair(&cfg, &var, &val)) {
                if (!strcasecmp(cfg.category, "settings")) {
@@ -1396,6 +1479,15 @@ static int config_exosip(int reload)
                                globals.rtp_end = atoi(val);
                        } else if (!strcmp(var, "codec_ms")) {
                                globals.codec_ms = atoi(val);
+                       } else if (!strcmp(var, "supress_telephony_events")) {
+                               globals.supress_telephony_events = switch_true(val);
+                       } else if (!strcmp(var, "dtmf_duration")) {
+                               int dur = atoi(val);
+                               if (dur > 10 && dur < 8000) {
+                                       globals.dtmf_duration = dur;
+                               } else {
+                                       switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Duration out of bounds!\n");
+                               }
                        }
                }
        }
index bdf90c1db8c0134addcd23e09877ce26d9d461dd..a6f7db47119396d17e5619ae7f6de0c4acb8829f 100644 (file)
@@ -72,6 +72,7 @@ static struct {
        int mtu;
        int dtmf_on;
        int dtmf_off;
+       int supress_dtmf_tone;
        char *dialplan;
 } globals;
 
@@ -572,6 +573,9 @@ static switch_status wanpipe_read_frame(switch_core_session *session, switch_fra
                if (globals.debug) {
                        switch_console_printf(SWITCH_CHANNEL_CONSOLE, "DTMF DETECTED: [%s]\n", digit_str);
                }
+               if (globals.supress_dtmf_tone) {
+                       memset(tech_pvt->read_frame.data, 0, tech_pvt->read_frame.datalen);
+               }
        }
 
        *frame = &tech_pvt->read_frame;
@@ -1093,6 +1097,8 @@ static int config_wanpipe(int reload)
                                globals.dtmf_on = atoi(val);
                        } else if (!strcmp(var, "dtmf_off")) {
                                globals.dtmf_off = atoi(val);
+                       } else if (!strcmp(var, "supress_dtmf_tone")) {
+                               globals.supress_dtmf_tone = switch_true(val);
                        }
                } else if (!strcasecmp(cfg.category, "span")) {
                        if (!strcmp(var, "span")) {
index 9e4755a150d8749cbeb0418c840e7be90f91b175..3f165e931a852a63bcb7cae55d072d06638df911 100644 (file)
  */
 #include <switch.h>
 
+static int RUNNING = 0;
+
+static int handle_SIGHUP(int sig)
+{
+       RUNNING = 0;
+       return 0;
+}
+
 int main(int argc, char *argv[])
 {
        char *err = NULL;
@@ -60,8 +68,16 @@ int main(int argc, char *argv[])
 
        switch_console_printf(SWITCH_CHANNEL_CONSOLE, "freeswitch Version %s Started\n\n", SWITCH_VERSION_FULL);
 
-       /* wait for console input */
-       switch_console_loop();
+       if (argv[1] && !strcmp(argv[1], "-nc")) {
+               (void) signal(SIGHUP, (void *) handle_SIGHUP);
+               RUNNING = 1;
+               while(RUNNING) {
+                       switch_yield(10000);
+               }
+       } else {
+               /* wait for console input */
+               switch_console_loop();
+       }
 
        if (switch_event_create(&event, SWITCH_EVENT_SHUTDOWN) == SWITCH_STATUS_SUCCESS) {
                switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Event-Info", "System Shutting Down");
index 23ceee93a9e4284219a77e5b0c1719b356271ecb..66f507a20ae4c06cd0124535d2b0aa421386c43b 100644 (file)
  */
 #include <switch_utils.h>
 
+static char RFC2833_CHARS[] = "0123456789*#ABCDF";
+
+SWITCH_DECLARE(char) switch_rfc2833_to_char(int event)
+{
+    return (event > -1 && event < sizeof(RFC2833_CHARS)) ? RFC2833_CHARS[event] : '\0';
+}
+
+SWITCH_DECLARE(int) switch_char_to_rfc2833(char key)
+{
+    char *c;
+
+    for (c = RFC2833_CHARS; *c ; c++) {
+        if (*c == key) {
+            return (c - RFC2833_CHARS);
+        }
+    }
+    return -1;
+}
+
 SWITCH_DECLARE(unsigned int) switch_separate_string(char *buf, char delim, char **array, int arraylen)
 {
        int argc;