]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-9904 #resolve cleanup and refactor msrp
authorSeven Du <dujinfang@gmail.com>
Mon, 2 Jan 2017 02:41:37 +0000 (10:41 +0800)
committerSeven Du <dujinfang@gmail.com>
Tue, 7 Feb 2017 12:41:46 +0000 (20:41 +0800)
src/include/switch_msrp.h
src/mod/endpoints/mod_sofia/mod_sofia.c
src/switch_core_media.c
src/switch_msrp.c

index 101f87178a6c7ca781902526cacc74fec09d4f80..25f51e954c468db384be858d195b023e7efba90f 100644 (file)
@@ -48,10 +48,9 @@ enum {
        MSRP_METHOD_SEND,
        MSRP_METHOD_AUTH,
        MSRP_METHOD_REPORT,
-
 };
 
-enum {
+typedef enum {
        MSRP_H_FROM_PATH,
        MSRP_H_TO_PATH,
        MSRP_H_MESSAGE_ID,
@@ -60,8 +59,14 @@ enum {
        MSRP_H_FAILURE_REPORT,
        MSRP_H_STATUS,
        MSRP_H_KEEPALIVE,
+
+       /* Fake headers */
+       MSRP_H_TRASACTION_ID,
+       MSRP_H_DELIMITER,
+       MSRP_H_CODE_DESCRIPTION,
+
        MSRP_H_UNKNOWN
-};
+} switch_msrp_header_type_t;
 
 typedef struct switch_msrp_session_s switch_msrp_session_t;
 typedef struct msrp_client_socket_s switch_msrp_client_socket_t;
@@ -70,16 +75,16 @@ typedef struct msrp_socket_s switch_msrp_socket_t;
 typedef struct msrp_msg_s {
        int state;
        int method;
-       char *headers[12];
-       int last_header;
-       char *transaction_id;
-       char *delimiter;
+       switch_event_t *headers;
+       const char *transaction_id;
+       const char *delimiter;
        int code_number;
-       char *code_description;
+       const char *code_description;
        switch_size_t byte_start;
        switch_size_t byte_end;
        switch_size_t bytes;
        switch_size_t payload_bytes;
+       switch_size_t accumulated_bytes;
        int range_star; /* range-end is '*' */
        char *last_p;
        char *payload;
@@ -125,7 +130,15 @@ SWITCH_DECLARE(switch_status_t) switch_msrp_perform_send(switch_msrp_session_t *
 SWITCH_DECLARE(switch_status_t) switch_msrp_start_client(switch_msrp_session_t *msrp_session);
 SWITCH_DECLARE(const char *) switch_msrp_listen_ip(void);
 
+SWITCH_DECLARE(switch_msrp_msg_t*) switch_msrp_msg_create();
+SWITCH_DECLARE(void) switch_msrp_msg_destroy(switch_msrp_msg_t **msg);
+
 SWITCH_DECLARE(void) switch_msrp_load_apis_and_applications(switch_loadable_module_interface_t **moudle_interface);
+SWITCH_DECLARE(const char*) switch_msrp_msg_get_header(switch_msrp_msg_t *msrp_msg, switch_msrp_header_type_t htype);
+SWITCH_DECLARE(switch_status_t) switch_msrp_msg_add_header(switch_msrp_msg_t *msrp_msg, switch_msrp_header_type_t htype, char *fmt, ...);
+SWITCH_DECLARE(void) switch_msrp_msg_set_payload(switch_msrp_msg_t *msrp_msg, const char *buf, switch_size_t payload_bytes);
+SWITCH_DECLARE(char*) switch_msrp_header_name(switch_msrp_header_type_t htype);
+SWITCH_DECLARE(switch_msrp_msg_t *) switch_msrp_msg_dup(switch_msrp_msg_t *msg);
 
 #define switch_msrp_send(ms, msg) switch_msrp_perform_send(ms, msg, __FILE__, __SWITCH_FUNC__, __LINE__)
 
index c988cee5bc81658681e9e5d05e174dfddb4bc657..a8299fe16d7c96ce0ce74ee48db14a2cc6ee6628 100644 (file)
@@ -958,46 +958,40 @@ static switch_status_t sofia_read_text_frame(switch_core_session_t *session, swi
                switch_msrp_session_t *msrp_session = switch_core_media_get_msrp_session(session);
                switch_frame_t *rframe = &msrp_session->frame;
                switch_msrp_msg_t *msrp_msg = switch_msrp_session_pop_msg(msrp_session);
+               const char *msrp_h_content_type = NULL;
 
-               rframe->flags = 0;
-
-#if 0
-               if (msrp_msg && msrp_msg->method == MSRP_METHOD_SEND) { /*echo back*/
-                       char *p;
-                       p = msrp_msg->headers[MSRP_H_TO_PATH];
-                       msrp_msg->headers[MSRP_H_TO_PATH] = msrp_msg->headers[MSRP_H_FROM_PATH];
-                       msrp_msg->headers[MSRP_H_FROM_PATH] = p;
-                       switch_msrp_send(msrp_session, msrp_msg);
+               if (msrp_msg) {
+                       msrp_h_content_type = switch_msrp_msg_get_header(msrp_msg, MSRP_H_CONTENT_TYPE);
                }
-#endif
 
+               rframe->flags = 0;
                rframe->data = msrp_session->frame_data;
                rframe->buflen = sizeof(msrp_session->frame_data);
 
                if (msrp_msg && msrp_msg->method == MSRP_METHOD_SEND &&
+                       msrp_msg->payload &&
                        !switch_stristr("?OTRv3?", msrp_msg->payload) &&
                        !switch_stristr("application/im-iscomposing", msrp_msg->payload) &&
-                       msrp_msg->headers[MSRP_H_CONTENT_TYPE] &&
-                       (switch_stristr("text/plain", msrp_msg->headers[MSRP_H_CONTENT_TYPE]) ||
-                        switch_stristr("text/html", msrp_msg->headers[MSRP_H_CONTENT_TYPE]) ||
-                        switch_stristr("message/cpim", msrp_msg->headers[MSRP_H_CONTENT_TYPE]))) {
+                       msrp_h_content_type &&
+                       (switch_stristr("text/plain", msrp_h_content_type) ||
+                        switch_stristr("text/html", msrp_h_content_type) ||
+                        switch_stristr("message/cpim", msrp_h_content_type))) {
+
                        rframe->datalen = msrp_msg->payload_bytes;
-                       rframe->packetlen = msrp_msg->payload_bytes;
-                       memcpy(rframe->data, msrp_msg->payload, msrp_msg->payload_bytes);
-                       
+                       rframe->packetlen = msrp_msg->payload_bytes + 12;
+                       memcpy(rframe->data, msrp_msg->payload, msrp_msg->payload_bytes + 1); /* include the last NULL byte */
+
                        rframe->m = 1;
-                       
                        *frame = rframe;
-                       
-                       if (msrp_msg->headers[MSRP_H_CONTENT_TYPE] && !strcasecmp(msrp_msg->headers[MSRP_H_CONTENT_TYPE], "message/cpim")) {
+
+                       if (msrp_h_content_type && !strcasecmp(msrp_h_content_type, "message/cpim")) {
                                char *stripped_text = switch_html_strip((char *)rframe->data);
                                memcpy(rframe->data, stripped_text, strlen(stripped_text)+1);
                                rframe->datalen = strlen(stripped_text)+1;
                                free(stripped_text);
                        }
 
-                       switch_safe_free(msrp_msg);
-                       msrp_msg = NULL;
+                       switch_msrp_msg_destroy(&msrp_msg);
                        status = SWITCH_STATUS_SUCCESS;
                } else {
                        rframe->datalen = 2;
@@ -1009,8 +1003,6 @@ static switch_status_t sofia_read_text_frame(switch_core_session_t *session, swi
                return status;
        }
 
-
-
        return switch_core_media_read_frame(session, frame, flags, stream_id, SWITCH_MEDIA_TYPE_TEXT);
 }
 
@@ -1020,13 +1012,15 @@ static switch_status_t sofia_write_text_frame(switch_core_session_t *session, sw
                switch_msrp_session_t *msrp_session = switch_core_media_get_msrp_session(session);
 
                if (frame && msrp_session) {
-                       switch_msrp_msg_t msrp_msg = { 0 };
-
-                       //msrp_msg.headers[MSRP_H_CONTENT_TYPE] = "message/cpim";
-                       msrp_msg.headers[MSRP_H_CONTENT_TYPE] = "text/plain";
-                       msrp_msg.payload = frame->data;
-                       msrp_msg.payload_bytes = frame->datalen;
-                       return switch_msrp_send(msrp_session, &msrp_msg);
+                       switch_msrp_msg_t *msrp_msg = switch_msrp_msg_create();
+                       switch_status_t status = SWITCH_STATUS_SUCCESS;
+
+                       // switch_msrp_msg_add_header(&msrp_msg, MSRP_H_CONTENT_TYPE, "message/cpim");
+                       switch_msrp_msg_add_header(msrp_msg, MSRP_H_CONTENT_TYPE, "text/plain");
+                       switch_msrp_msg_set_payload(msrp_msg, frame->data, frame->datalen);
+                       status = switch_msrp_send(msrp_session, msrp_msg);
+                       switch_msrp_msg_destroy(&msrp_msg);
+                       return status;
                }
 
                return SWITCH_STATUS_FALSE;
index ca5fce75a7e2e42fdb43f45fe9c7d55fc77599de..bcc7c2861df961717dd49655a070a2007a01f475 100644 (file)
@@ -10509,7 +10509,7 @@ SWITCH_DECLARE(void) switch_core_media_gen_local_sdp(switch_core_session_t *sess
                                msrp_session->active ? "active" : "passive");
 
                        if (!zstr(file_selector)) {
-                               switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
+                               switch_snprintf(buf + strlen(buf), SDPBUFLEN - strlen(buf),
                                        "a=sendonly\na=file-selector:%s\n", file_selector);
                        }
                }
index 8009f8a88da6de26605c60abeab15704d3d336f6..81c9cd0638ee62d2c78a92d2f76d0022408c0c7a 100644 (file)
@@ -34,7 +34,7 @@
 #include <switch_msrp.h>
 #include <switch_stun.h>
 
-#define MSRP_BUFF_SIZE SWITCH_RTP_MAX_BUF_LEN
+#define MSRP_BUFF_SIZE (SWITCH_RTP_MAX_BUF_LEN - 32)
 #define DEBUG_MSRP 0
 #define MSRP_LISTEN_PORT 2855
 #define MSRP_SSL_LISTEN_PORT 2856
@@ -81,6 +81,26 @@ typedef struct worker_helper{
        switch_msrp_session_t *msrp_session;
 } worker_helper_t;
 
+SWITCH_DECLARE(void) switch_msrp_msg_set_payload(switch_msrp_msg_t *msrp_msg, const char *buf, switch_size_t payload_bytes)
+{
+       if (!msrp_msg->payload) {
+               switch_malloc(msrp_msg->payload, payload_bytes + 1);
+       } else if (msrp_msg->payload_bytes < payload_bytes + 1) {
+               msrp_msg->payload = realloc(msrp_msg->payload, payload_bytes + 1);
+       }
+
+       switch_assert(msrp_msg->payload);
+       memcpy(msrp_msg->payload, buf, payload_bytes);
+       *(msrp_msg->payload + payload_bytes) = '\0';
+       msrp_msg->payload_bytes = payload_bytes;
+}
+
+static switch_bool_t msrp_check_success_report(switch_msrp_msg_t *msrp_msg)
+{
+       const char *msrp_h_success_report = switch_msrp_msg_get_header(msrp_msg, MSRP_H_SUCCESS_REPORT);
+       return (msrp_h_success_report && !strcmp(msrp_h_success_report, "yes"));
+}
+
 static void msrp_deinit_ssl()
 {
        if (globals.ssl_ctx) {
@@ -378,11 +398,6 @@ SWITCH_DECLARE(switch_status_t) switch_msrp_session_destroy(switch_msrp_session_
 switch_status_t switch_msrp_session_push_msg(switch_msrp_session_t *ms, switch_msrp_msg_t *msg)
 {
        switch_mutex_lock(ms->mutex);
-
-       if (msg->payload && msg->payload_bytes) { /* add NULL byte */
-               *((char *)msg->payload + msg->payload_bytes) = '\0';
-               msg->payload_bytes++;
-       }
        
        if (ms->last_msg == NULL) {
                ms->last_msg = msg;
@@ -391,24 +406,42 @@ switch_status_t switch_msrp_session_push_msg(switch_msrp_session_t *ms, switch_m
                ms->last_msg->next = msg;
                ms->last_msg = msg;
        }
+
        ms->msrp_msg_count++;
+
        switch_mutex_unlock(ms->mutex);
+
        return SWITCH_STATUS_SUCCESS;
 }
 
 SWITCH_DECLARE(switch_msrp_msg_t *)switch_msrp_session_pop_msg(switch_msrp_session_t *ms)
 {
-       switch_msrp_msg_t *m = ms->msrp_msg;
+       switch_msrp_msg_t *m = NULL;
+
+       switch_mutex_lock(ms->mutex);
+
+       m = ms->msrp_msg;
+
        if (m == NULL) {
+               switch_mutex_unlock(ms->mutex);
                switch_yield(20000);
+               switch_mutex_lock(ms->mutex);
+       }
+
+       m = ms->msrp_msg;
+
+       if (m == NULL) {
+               switch_mutex_unlock(ms->mutex);
                return NULL;
        }
 
-       switch_mutex_lock(ms->mutex);
        ms->msrp_msg = ms->msrp_msg->next;
        ms->msrp_msg_count--;
+
        if (ms->msrp_msg == NULL) ms->last_msg = NULL;
+
        switch_mutex_unlock(ms->mutex);
+
        return m;
 }
 
@@ -423,19 +456,20 @@ switch_status_t msrp_msg_serialize(switch_msrp_msg_t *msrp_msg, char *buf)
                case MSRP_METHOD_REPORT: sprintf(method, "REPORT"); break;
                default: sprintf(method, "%d", msrp_msg->method); break;
        }
+
        sprintf(buf, "=================================\n"
                "MSRP %s %s%s\nFrom: %s\nTo: %s\nMessage-ID: %s\n"
                "Content-Type: %s\n"
                "Byte-Range: %" SWITCH_SIZE_T_FMT "-%" SWITCH_SIZE_T_FMT"/%" SWITCH_SIZE_T_FMT "\n"
                "Payload:\n%s\n%s\n"
                "=================================\n",
-               msrp_msg->transaction_id ? switch_str_nil(msrp_msg->transaction_id) : code_number_str,
+               msrp_msg->transaction_id ? msrp_msg->transaction_id : code_number_str,
                msrp_msg->transaction_id ? "" : " ",
-               msrp_msg->transaction_id ? method : switch_str_nil(msrp_msg->code_description),
-               switch_str_nil(msrp_msg->headers[MSRP_H_FROM_PATH]),
-               switch_str_nil(msrp_msg->headers[MSRP_H_TO_PATH]),
-               switch_str_nil(msrp_msg->headers[MSRP_H_MESSAGE_ID]),
-               switch_str_nil(msrp_msg->headers[MSRP_H_CONTENT_TYPE]),
+               msrp_msg->transaction_id ? method : msrp_msg->code_description,
+               switch_msrp_msg_get_header(msrp_msg, MSRP_H_FROM_PATH),
+               switch_msrp_msg_get_header(msrp_msg, MSRP_H_TO_PATH),
+               switch_msrp_msg_get_header(msrp_msg, MSRP_H_MESSAGE_ID),
+               switch_msrp_msg_get_header(msrp_msg, MSRP_H_CONTENT_TYPE),
                msrp_msg->byte_start,
                msrp_msg->byte_end,
                msrp_msg->bytes,
@@ -471,6 +505,8 @@ static switch_status_t msrp_socket_recv(switch_msrp_client_socket_t *csock, char
 
 static switch_status_t msrp_socket_send(switch_msrp_client_socket_t *csock, char *buf, switch_size_t *len)
 {
+       // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "send: %s\n", buf);
+
        if (csock->secure) {
                *len = SSL_write(csock->ssl, buf, *len);
                return *len ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
@@ -479,7 +515,7 @@ static switch_status_t msrp_socket_send(switch_msrp_client_socket_t *csock, char
        }
 }
 
-void dump_buffer(char *buf, switch_size_t len, int line)
+void dump_buffer(const char *buf, switch_size_t len, int line)
 {
        int i, j, k = 0;
        char buff[MSRP_BUFF_SIZE * 2];
@@ -508,13 +544,13 @@ void dump_buffer(char *buf, switch_size_t len, int line)
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%d: [%" SWITCH_SIZE_T_FMT "] ::DUMP::%s::DUMP::\n", line, len, buff);
 }
 
-char *find_delim(char *buf, int len, char *delim)
+char *find_delim(char *buf, int len, const char *delim)
 {
        char *p, *q, *s = NULL;
        char *end;
 
        p = buf;
-       q = delim;
+       q = (char *)delim;
 
        if (p == NULL) return NULL;
        if (q == NULL) return NULL;
@@ -529,7 +565,7 @@ char *find_delim(char *buf, int len, char *delim)
                        } else {
                                        s = NULL;
                                        p++;
-                                       q = delim;
+                                       q = (char *)delim;
                        }
                        if (*q == '\0') return s;
        }
@@ -545,7 +581,68 @@ Byte-Range: 1-0/0
 -------d4c667b2351e958f$
 */
 
-char *msrp_parse_header(char *start, int skip, const char *end, switch_msrp_msg_t *msrp_msg, int index, switch_memory_pool_t *pool)
+char* HEADER_NAMES[] = {
+       "MSRP_H_FROM_PATH",
+       "MSRP_H_TO_PATH",
+       "MSRP_H_MESSAGE_ID",
+       "MSRP_H_CONTENT_TYPE",
+       "MSRP_H_SUCCESS_REPORT",
+       "MSRP_H_FAILURE_REPORT",
+       "MSRP_H_STATUS",
+       "MSRP_H_KEEPALIVE",
+
+       "MSRP_H_TRASACTION_ID",
+       "MSRP_H_DELIMITER",
+
+       "MSRP_H_UNKNOWN"
+};
+
+SWITCH_DECLARE(char*) switch_msrp_msg_header_name(switch_msrp_header_type_t htype) {
+       if (htype > MSRP_H_UNKNOWN) htype = MSRP_H_UNKNOWN;
+
+       return HEADER_NAMES[htype];
+}
+
+SWITCH_DECLARE(switch_status_t) switch_msrp_msg_add_header(switch_msrp_msg_t *msrp_msg, switch_msrp_header_type_t htype, char *fmt, ...)
+{
+       switch_status_t status;
+
+       int ret = 0;
+       char *data;
+       va_list ap;
+
+       va_start(ap, fmt);
+       ret = switch_vasprintf(&data, fmt, ap);
+       va_end(ap);
+
+       if (ret == -1) {
+               return SWITCH_STATUS_MEMERR;
+       }
+
+       status = switch_event_add_header_string(msrp_msg->headers, SWITCH_STACK_BOTTOM, switch_msrp_msg_header_name(htype), data);
+
+       switch (htype) {
+       case MSRP_H_TRASACTION_ID:
+               msrp_msg->transaction_id = switch_msrp_msg_get_header(msrp_msg, MSRP_H_TRASACTION_ID);
+               break;
+       case MSRP_H_DELIMITER:
+               msrp_msg->delimiter = switch_msrp_msg_get_header(msrp_msg, MSRP_H_DELIMITER);
+               break;
+       case MSRP_H_CODE_DESCRIPTION:
+               msrp_msg->code_description = switch_msrp_msg_get_header(msrp_msg, MSRP_H_CODE_DESCRIPTION);
+               break;
+       default: break;
+       }
+
+       return status;
+}
+
+SWITCH_DECLARE(const char *) switch_msrp_msg_get_header(switch_msrp_msg_t *msrp_msg, switch_msrp_header_type_t htype) {
+       char *v = switch_event_get_header(msrp_msg->headers, switch_msrp_msg_header_name(htype));
+       return v;
+}
+
+char *msrp_parse_header(char *start, int skip, const char *end, switch_msrp_msg_t *msrp_msg, switch_msrp_header_type_t htype, switch_memory_pool_t *pool)
 {
        char *p = start + skip;
        char *q;
@@ -555,40 +652,39 @@ char *msrp_parse_header(char *start, int skip, const char *end, switch_msrp_msg_
        if (q > p) {
                if (*(q-1) == '\r') *(q-1) = '\0';
                *q = '\0';
-               msrp_msg->headers[index] = switch_core_strdup(pool, p);
-               msrp_msg->last_header = msrp_msg->last_header > index ? msrp_msg->last_header : index;
+               switch_msrp_msg_add_header(msrp_msg, htype, p);
                return q + 1;
        }
        return start;
 }
 
-switch_msrp_msg_t *msrp_parse_headers(const char *start, int len, switch_msrp_msg_t *msrp_msg, switch_memory_pool_t *pool)
+switch_msrp_msg_t *msrp_parse_headers(char *start, int len, switch_msrp_msg_t *msrp_msg, switch_memory_pool_t *pool)
 {
-       char *p = (char *)start;
+       char *p = start;
        char *q = p;
        const char *end = start + len;
-       int headers = 0;
-       char line[1024];
-
 
        while(p < end) {
                if (!strncasecmp(p, "MSRP ", 5)) {
                        p += 5;
                        q = p;
+
                        while(*q && q < end && *q != ' ') q++;
+
                        if (q > p) {
                                *q = '\0';
-                               msrp_msg->transaction_id = switch_core_strdup(pool, p);
-                               switch_snprintf(line, 128, "-------%s", msrp_msg->transaction_id);
-                               msrp_msg->delimiter = switch_core_strdup(pool, line);
+                               switch_msrp_msg_add_header(msrp_msg, MSRP_H_TRASACTION_ID, p);
+                               switch_msrp_msg_add_header(msrp_msg, MSRP_H_DELIMITER, "-------%s", p);
                                msrp_msg->state = MSRP_ST_PARSE_HEADER;
                        }
+
                        p = q;
+
                        if (++p >= end) goto done;
 
                        if (!strncasecmp(p, "SEND", 4)) {
                                msrp_msg->method = MSRP_METHOD_SEND;
-                               p +=6; /*skip \r\n*/
+                               p += 6; /*skip \r\n*/
                        } else if (!strncasecmp(p, "REPORT", 6)) {
                                msrp_msg->method = MSRP_METHOD_REPORT;
                                p += 8;
@@ -607,12 +703,11 @@ switch_msrp_msg_t *msrp_parse_headers(const char *start, int len, switch_msrp_ms
                                        if (q > p) {
                                                if (*(q-1) == '\r') *(q-1) = '\0';
                                                *q = '\0';
-                                               msrp_msg->code_description = switch_core_strdup(pool, p);
+                                               switch_msrp_msg_add_header(msrp_msg, MSRP_H_CODE_DESCRIPTION, p);
                                                p = ++q;
                                        }
                                }
                        }
-                       headers++;
                } else if (!strncasecmp(p, "From-Path:", 10)) {
                        q = msrp_parse_header(p, 10, end, msrp_msg, MSRP_H_FROM_PATH, pool);
                        if (q == p) break; /* incomplete header*/
@@ -686,7 +781,6 @@ switch_msrp_msg_t *msrp_parse_headers(const char *start, int len, switch_msrp_ms
                                        }
                                }
                        }
-                       headers++;
                } else if (*p == '\r' && *(p+1) == '\n') {
                        msrp_msg->state = MSRP_ST_WAIT_BODY;
                        p += 2;
@@ -713,7 +807,7 @@ switch_msrp_msg_t *msrp_parse_headers(const char *start, int len, switch_msrp_ms
                                        }
                                }
                                break;
-               } else {/* unsupported header*/
+               } else {/* unsupported header */
                        q = p;
                        while(*q && q < end && *q != ':') q++;
                        if (q > p) {
@@ -721,11 +815,10 @@ switch_msrp_msg_t *msrp_parse_headers(const char *start, int len, switch_msrp_ms
                                *q = '\0';
                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "unsupported header [%s]\n", p);
                                p = q + 1;
-                               msrp_msg->last_header = msrp_msg->last_header == 0 ? MSRP_H_UNKNOWN : msrp_msg->last_header + 1;
-                               q = msrp_parse_header(p, 0, end, msrp_msg, msrp_msg->last_header, pool);
+                               q = msrp_parse_header(p, 0, end, msrp_msg, MSRP_H_UNKNOWN, pool);
                                if (q == p) {
                                        p = last_p;
-                                       break; /* incomplete header*/
+                                       break; /* incomplete header */
                                }
                                p = q;
                        }
@@ -739,11 +832,10 @@ done:
 
 switch_msrp_msg_t *msrp_parse_buffer(char *buf, int len, switch_msrp_msg_t *msrp_msg, switch_memory_pool_t *pool)
 {
-       const char *start;
+       char *start;
 
        if (!msrp_msg) {
-               switch_zmalloc(msrp_msg, sizeof(switch_msrp_msg_t));
-               switch_assert(msrp_msg);
+               msrp_msg = switch_msrp_msg_create();
                msrp_msg->state = MSRP_ST_WAIT_HEADER;
        }
 
@@ -753,10 +845,11 @@ switch_msrp_msg_t *msrp_parse_buffer(char *buf, int len, switch_msrp_msg_t *msrp
        }
 
        if (msrp_msg->state == MSRP_ST_WAIT_HEADER) {
-               if ((start = switch_stristr("MSRP ", buf)) == NULL) {
+               if ((start = (char *)switch_stristr("MSRP ", buf)) == NULL) {
                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Not an MSRP packet, Skip!\n");
                        return msrp_msg;
                }
+
                msrp_msg = msrp_parse_headers(start, len - (start - buf), msrp_msg, pool);
 
                if (msrp_msg->state == MSRP_ST_ERROR) return msrp_msg;
@@ -770,62 +863,70 @@ switch_msrp_msg_t *msrp_parse_buffer(char *buf, int len, switch_msrp_msg_t *msrp
                        msrp_msg->state = MSRP_ST_DONE;
                        return msrp_msg;
                }
+
                if (msrp_msg->range_star) { /* the * case */
                        /*hope we can find the delimiter at the end*/
                        int dlen;
                        char *delim_pos = NULL;
+                       switch_size_t payload_bytes;
+
                        switch_assert(msrp_msg->delimiter);
                        dlen = strlen(msrp_msg->delimiter);
+
                        if (!strncmp(buf + len - dlen - 3, msrp_msg->delimiter, dlen)) { /*bingo*/
-                               msrp_msg->payload_bytes = len - dlen - 5;
-                               msrp_msg->payload = switch_core_alloc(pool, msrp_msg->payload_bytes + 1);
-                               switch_assert(msrp_msg->payload);
-                               memcpy(msrp_msg->payload, buf, msrp_msg->payload_bytes);
-                               msrp_msg->byte_end = msrp_msg->byte_start + msrp_msg->payload_bytes - 1;
+                               payload_bytes = len - dlen - 5;
+                               switch_msrp_msg_set_payload(msrp_msg, buf, payload_bytes);
+                               msrp_msg->byte_end = msrp_msg->byte_start + payload_bytes - 1;
                                msrp_msg->state = MSRP_ST_DONE;
                                msrp_msg->last_p = buf + len;
+                               if (msrp_msg->accumulated_bytes) {
+                                       msrp_msg->accumulated_bytes += payload_bytes;
+                               }
                                return msrp_msg;
-                       } else if ((delim_pos = find_delim(buf, len, msrp_msg->delimiter))){
+                       } else if ((delim_pos = find_delim(buf, len, msrp_msg->delimiter))) {
                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "=======================================delimiter: %s\n", delim_pos);
-                               msrp_msg->payload_bytes = delim_pos - buf - 2;
-                               // if (msrp_msg->payload_bytes < 0) msrp_msg->payload_bytes = 0;
-                               msrp_msg->payload = switch_core_alloc(pool, msrp_msg->payload_bytes + 1);
-                               switch_assert(msrp_msg->payload);
-                               memcpy(msrp_msg->payload, buf, msrp_msg->payload_bytes);
+                               payload_bytes = delim_pos - buf - 2;
+                               switch_assert(payload_bytes >= 0);
+                               switch_msrp_msg_set_payload(msrp_msg, buf, payload_bytes);
                                msrp_msg->byte_end = msrp_msg->byte_start + msrp_msg->payload_bytes - 1;
                                msrp_msg->state = MSRP_ST_DONE;
                                msrp_msg->last_p = delim_pos + dlen + 3;
+                               if (msrp_msg->accumulated_bytes) {
+                                       msrp_msg->accumulated_bytes += payload_bytes;
+                               }
                                return msrp_msg;
                        } else {/* keep waiting*/
-                               /*TODO: fix potential overflow here*/
                                msrp_msg->last_p = buf;
                                return msrp_msg;
                        }
                } else if (msrp_msg->payload_bytes == 0) {
                        int dlen = strlen(msrp_msg->delimiter);
-                       if(strncasecmp(buf, msrp_msg->delimiter, dlen)) {
+
+                       if (strncasecmp(buf, msrp_msg->delimiter, dlen)) {
                                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error find delimiter\n");
                                msrp_msg->state = MSRP_ST_ERROR;
                                return msrp_msg;
                        }
+
                        msrp_msg->payload = NULL;
                        msrp_msg->state = MSRP_ST_DONE;
                        msrp_msg->last_p = buf + dlen + 3; /*Fixme: assuming end with $\r\n*/
+
                        return msrp_msg;
                } else {
                        int dlen = strlen(msrp_msg->delimiter);
 
                        if (msrp_msg->payload_bytes > len) {
-                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Waiting payload... %d < %d\n", (int)msrp_msg->payload_bytes, (int)len);
-                               return msrp_msg; /*keep waiting ?*/
+                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "payload too large ... %d > %d\n", (int)msrp_msg->payload_bytes, (int)len);
+                               msrp_msg->state = MSRP_ST_ERROR; // not supported yet
+                               return msrp_msg;
                        }
 
-                       msrp_msg->payload = switch_core_alloc(pool, msrp_msg->payload_bytes);
-                       switch_assert(msrp_msg->payload);
-                       memcpy(msrp_msg->payload, buf, msrp_msg->payload_bytes);
+                       switch_msrp_msg_set_payload(msrp_msg, buf, msrp_msg->payload_bytes);
                        msrp_msg->last_p = buf + msrp_msg->payload_bytes;
                        msrp_msg->state = MSRP_ST_DONE;
                        msrp_msg->last_p = buf + msrp_msg->payload_bytes;
+
                        if (msrp_msg->payload_bytes == len - dlen - 5) {
                                msrp_msg->last_p = buf + len;
 
@@ -833,28 +934,28 @@ switch_msrp_msg_t *msrp_parse_buffer(char *buf, int len, switch_msrp_msg_t *msrp
 
                                return msrp_msg; /*Fixme: assuming \r\ndelimiter$\r\n present*/
                        }
-                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%" SWITCH_SIZE_T_FMT " %d %d\n", msrp_msg->payload_bytes, len, dlen);
 
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%" SWITCH_SIZE_T_FMT " %d %d\n", msrp_msg->payload_bytes, len, dlen);
                        msrp_msg->state = MSRP_ST_ERROR;
+
                        return msrp_msg;
                }
        } else {
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error here! code:%d\n", msrp_msg->state);
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error code: %d\n", msrp_msg->state);
        }
 
        return msrp_msg;
 }
 
-
 switch_status_t msrp_reply(switch_msrp_client_socket_t *csock, switch_msrp_msg_t *msrp_msg)
 {
        char buf[2048];
        switch_size_t len;
        sprintf(buf, "MSRP %s 200 OK\r\nTo-Path: %s\r\nFrom-Path: %s\r\n"
                "%s$\r\n",
-               switch_str_nil(msrp_msg->transaction_id),
-               switch_str_nil(msrp_msg->headers[MSRP_H_FROM_PATH]),
-               switch_str_nil(msrp_msg->headers[MSRP_H_TO_PATH]),
+               msrp_msg->transaction_id,
+               switch_str_nil(switch_msrp_msg_get_header(msrp_msg, MSRP_H_FROM_PATH)),
+               switch_str_nil(switch_msrp_msg_get_header(msrp_msg, MSRP_H_TO_PATH)),
                msrp_msg->delimiter);
        len = strlen(buf);
 
@@ -868,20 +969,22 @@ switch_status_t msrp_report(switch_msrp_client_socket_t *csock, switch_msrp_msg_
        sprintf(buf, "MSRP %s REPORT\r\nTo-Path: %s\r\nFrom-Path: %s\r\nMessage-ID: %s\r\n"
                "Status: 000 %s\r\nByte-Range: 1-%" SWITCH_SIZE_T_FMT "/%" SWITCH_SIZE_T_FMT
                "\r\n%s$\r\n",
-               switch_str_nil(msrp_msg->transaction_id),
-               switch_str_nil(msrp_msg->headers[MSRP_H_FROM_PATH]),
-               switch_str_nil(msrp_msg->headers[MSRP_H_TO_PATH]),
-               switch_str_nil(msrp_msg->headers[MSRP_H_MESSAGE_ID]),
+               msrp_msg->transaction_id,
+               switch_str_nil(switch_msrp_msg_get_header(msrp_msg, MSRP_H_FROM_PATH)),
+               switch_str_nil(switch_msrp_msg_get_header(msrp_msg, MSRP_H_TO_PATH)),
+               switch_str_nil(switch_msrp_msg_get_header(msrp_msg, MSRP_H_MESSAGE_ID)),
                switch_str_nil(status_code),
-               msrp_msg->byte_end,
+               msrp_msg->accumulated_bytes ? msrp_msg->accumulated_bytes : msrp_msg->byte_end,
                msrp_msg->bytes,
                msrp_msg->delimiter);
        len = strlen(buf);
+
        if (globals.debug) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "report: %" SWITCH_SIZE_T_FMT " bytes\n%s", len, buf);
+
        return msrp_socket_send(csock, buf, &len);
 }
 
-static switch_bool_t msrp_find_uuid(char *uuid, char *to_path)
+static switch_bool_t msrp_find_uuid(char *uuid, const char *to_path)
 {
        int len = strlen(to_path);
        int i;
@@ -917,12 +1020,13 @@ static void *SWITCH_THREAD_FUNC msrp_worker(switch_thread_t *thread, void *obj)
 
        if (client_mode) {
                switch_sockaddr_t *sa = NULL;
-               switch_msrp_msg_t setup_msg = { 0 };
+               switch_msrp_msg_t *setup_msg = switch_msrp_msg_create();
                const char *remote_ip = NULL;
                switch_port_t remote_port = 0;
                char *dup = NULL;
                char *p = NULL;
 
+               switch_assert(setup_msg);
                switch_assert(helper->msrp_session);
                msrp_session = helper->msrp_session;
                msrp_session->running = 1;
@@ -1024,14 +1128,15 @@ static void *SWITCH_THREAD_FUNC msrp_worker(switch_thread_t *thread, void *obj)
 
                helper->msrp_session->csock = csock;
 
-               setup_msg.headers[MSRP_H_CONTENT_TYPE] = "text/plain";
-               setup_msg.payload = NULL;
-               setup_msg.payload_bytes = 0;
+               switch_msrp_msg_add_header(setup_msg, MSRP_H_CONTENT_TYPE, "text/plain");
 
-               if (SWITCH_STATUS_SUCCESS != switch_msrp_send(msrp_session, &setup_msg)) {
+               if (SWITCH_STATUS_SUCCESS != switch_msrp_send(msrp_session, setup_msg)) {
                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "MSRP initial setup send error!\n");
+                       switch_msrp_msg_destroy(&setup_msg);
                        goto end;
                }
+
+               switch_msrp_msg_destroy(&setup_msg);
        } else { // server mode
                switch_socket_opt_set(csock->sock, SWITCH_SO_TCP_NODELAY, TRUE);
                // switch_socket_opt_set(csock->sock, SWITCH_SO_NONBLOCK, TRUE);
@@ -1096,8 +1201,7 @@ static void *SWITCH_THREAD_FUNC msrp_worker(switch_thread_t *thread, void *obj)
 
                if (msrp_msg->state == MSRP_ST_DONE && msrp_msg->method == MSRP_METHOD_SEND) {
                        msrp_reply(csock, msrp_msg);
-                       if (msrp_msg->headers[MSRP_H_SUCCESS_REPORT] &&
-                               !strcmp(msrp_msg->headers[MSRP_H_SUCCESS_REPORT], "yes")) {
+                       if (msrp_check_success_report(msrp_msg)) {
                                msrp_report(csock, msrp_msg, "200 OK");
                        }
                } else if (msrp_msg->state == MSRP_ST_DONE && msrp_msg->method == MSRP_METHOD_AUTH) {
@@ -1107,7 +1211,7 @@ static void *SWITCH_THREAD_FUNC msrp_worker(switch_thread_t *thread, void *obj)
                        goto end;
                }
 
-               if (msrp_find_uuid(uuid, msrp_msg->headers[MSRP_H_TO_PATH]) != SWITCH_TRUE) {
+               if (msrp_find_uuid(uuid, switch_msrp_msg_get_header(msrp_msg, MSRP_H_TO_PATH)) != SWITCH_TRUE) {
                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid MSRP to-path!\n");
                }
 
@@ -1136,8 +1240,7 @@ static void *SWITCH_THREAD_FUNC msrp_worker(switch_thread_t *thread, void *obj)
        len = MSRP_BUFF_SIZE;
        p = buf;
        last_p = buf;
-       switch_safe_free(msrp_msg);
-       msrp_msg = NULL;
+       if (msrp_msg) switch_msrp_msg_destroy(&msrp_msg);
 
        while (msrp_socket_recv(csock, p, &len) == SWITCH_STATUS_SUCCESS && len > 0) {
                // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "read bytes:%" SWITCH_SIZE_T_FMT "\n", len);
@@ -1163,17 +1266,17 @@ static void *SWITCH_THREAD_FUNC msrp_worker(switch_thread_t *thread, void *obj)
 
                if (msrp_msg->state == MSRP_ST_DONE && msrp_msg->method == MSRP_METHOD_SEND) {
                        msrp_reply(csock, msrp_msg);
-                       if (msrp_msg->headers[MSRP_H_SUCCESS_REPORT] &&
-                               !strcmp(msrp_msg->headers[MSRP_H_SUCCESS_REPORT], "yes")) {
+
+                       if (msrp_check_success_report(msrp_msg)) {
                                msrp_report(csock, msrp_msg, "200 OK");
                        }
+
                        last_p = msrp_msg->last_p;
                        switch_msrp_session_push_msg(msrp_session, msrp_msg);
                        msrp_msg = NULL;
                } else if (msrp_msg->state == MSRP_ST_DONE) { /* throw away */
                        last_p = msrp_msg->last_p;
-                       switch_safe_free(msrp_msg);
-                       msrp_msg = NULL;
+                       switch_msrp_msg_destroy(&msrp_msg);
                } else {
                        last_p = msrp_msg->last_p;
                }
@@ -1183,7 +1286,7 @@ static void *SWITCH_THREAD_FUNC msrp_worker(switch_thread_t *thread, void *obj)
                        switch_yield(100000);
                }
 
-               if (p + len > last_p) {
+               if (p + len > last_p) { // unparsed msg in buffer
                        p += len;
                        if (!msrp_msg) {
                                int rest_len = p - last_p;
@@ -1196,6 +1299,7 @@ static void *SWITCH_THREAD_FUNC msrp_worker(switch_thread_t *thread, void *obj)
                        }
 
                        if (p >= buf + MSRP_BUFF_SIZE) {
+                               switch_msrp_msg_t *new_msg;
 
                                if (msrp_msg->state != MSRP_ST_WAIT_BODY || !msrp_msg->range_star) {
                                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "buffer overflow\n");
@@ -1203,47 +1307,27 @@ static void *SWITCH_THREAD_FUNC msrp_worker(switch_thread_t *thread, void *obj)
                                        break;
                                }
 
-                               /* buffer full*/
-                               msrp_msg->payload_bytes = p - last_p;
-                               msrp_msg->byte_end = msrp_msg->byte_start + msrp_msg->payload_bytes - 1;
-                               msrp_msg->payload = switch_core_alloc(pool, msrp_msg->payload_bytes);
-                               switch_assert(msrp_msg->payload);
-                               memcpy(msrp_msg->payload, last_p, msrp_msg->payload_bytes);
-
-                               {
-                                       int i;
-                                       switch_msrp_msg_t *msrp_msg_old = msrp_msg;
-                                       msrp_msg = NULL;
-                                       /*dup msrp_msg*/
-                                       switch_zmalloc(msrp_msg, sizeof(switch_msrp_msg_t));
-                                       switch_assert(msrp_msg);
-                                       msrp_msg->state = msrp_msg_old->state;
-                                       msrp_msg->byte_start = msrp_msg_old->byte_end + 1;
-                                       msrp_msg->bytes = msrp_msg_old->bytes;
-                                       msrp_msg->range_star = msrp_msg_old->range_star;
-                                       msrp_msg->method = msrp_msg_old->method;
-                                       msrp_msg->transaction_id = switch_core_strdup(pool, msrp_msg_old->transaction_id);
-                                       msrp_msg->delimiter = switch_core_strdup(pool, msrp_msg_old->delimiter);
-                                       msrp_msg->last_header = msrp_msg_old->last_header;
-
-                                       for (i = 0; i < msrp_msg->last_header; i++) {
-                                               msrp_msg->headers[i] = switch_core_strdup(pool, msrp_msg_old->headers[i]);
-                                       }
-
-                                       msrp_msg_old->state = MSRP_ST_DONE;
-
-                                       if (msrp_msg_old->headers[MSRP_H_SUCCESS_REPORT] &&
-                                               !strcmp(msrp_msg_old->headers[MSRP_H_SUCCESS_REPORT], "yes")) {
-                                               // msrp_report(csock, msrp_msg_old, "200 OK");
-                                       }
-
-                                       switch_msrp_session_push_msg(msrp_session, msrp_msg_old);
-                               }
+                               switch_assert(p == buf + MSRP_BUFF_SIZE);
 
+                               /* buffer full*/
+                               msrp_msg->payload_bytes = 0;
+                               new_msg = switch_msrp_msg_dup(msrp_msg);
+                               switch_msrp_msg_set_payload(new_msg, last_p, p - last_p);
+                               new_msg->state = MSRP_ST_DONE;
+                               switch_msrp_session_push_msg(msrp_session, new_msg);
+                               new_msg = NULL;
+
+                               msrp_msg->accumulated_bytes += (p - last_p);
                                p = buf;
                                len = MSRP_BUFF_SIZE;
                                last_p = buf;
                                msrp_msg->last_p = buf;
+                               msrp_msg->byte_start = msrp_msg->byte_end = 0;
+                               msrp_msg->payload_bytes = 0;
+
+                               if (globals.debug) {
+                                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "acc: %" SWITCH_SIZE_T_FMT "\n", msrp_msg->accumulated_bytes);
+                               }
                        }
                } else { /* all buffer parsed */
                        p = buf;
@@ -1372,8 +1456,10 @@ SWITCH_DECLARE(switch_status_t) switch_msrp_perform_send(switch_msrp_session_t *
        char transaction_id[MSRP_TRANS_ID_LEN + 1] = { 0 };
        char buf[MSRP_BUFF_SIZE];
        switch_size_t len;
-       char *to_path = msrp_msg->headers[MSRP_H_TO_PATH] ? msrp_msg->headers[MSRP_H_TO_PATH] : ms->remote_path;
-       char *from_path = msrp_msg->headers[MSRP_H_FROM_PATH] ? msrp_msg->headers[MSRP_H_FROM_PATH] : ms->local_path;
+       const char *msrp_h_to_path = switch_msrp_msg_get_header(msrp_msg, MSRP_H_TO_PATH);
+       const char *msrp_h_from_path = switch_msrp_msg_get_header(msrp_msg, MSRP_H_FROM_PATH);
+       const char *to_path = msrp_h_to_path ? msrp_h_to_path : ms->remote_path;
+       const char *from_path = msrp_h_from_path ? msrp_h_from_path: ms->local_path;
 
        if (!ms->running) {
                switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, ms->call_id, SWITCH_LOG_WARNING, "MSRP not ready! Discard one message\n");
@@ -1393,7 +1479,7 @@ SWITCH_DECLARE(switch_status_t) switch_msrp_perform_send(switch_msrp_session_t *
                transaction_id,
                to_path,
                from_path,
-               switch_str_nil(msrp_msg->headers[MSRP_H_CONTENT_TYPE]),
+               switch_str_nil(switch_msrp_msg_get_header(msrp_msg, MSRP_H_CONTENT_TYPE)),
                msrp_msg->payload ? msrp_msg->payload_bytes : 0,
                msrp_msg->payload ? msrp_msg->payload_bytes : 0,
                msrp_msg->payload ? "\r\n\r\n" : "");
@@ -1408,85 +1494,89 @@ SWITCH_DECLARE(switch_status_t) switch_msrp_perform_send(switch_msrp_session_t *
                memcpy(buf + len, msrp_msg->payload, msrp_msg->payload_bytes);
                len += msrp_msg->payload_bytes;
        }
+
        sprintf(buf + len, "\r\n-------%s$\r\n", transaction_id);
        len += (12 + strlen(transaction_id));
+
        if (globals.debug) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "---------------------send: %" SWITCH_SIZE_T_FMT " bytes---------------------\n%s\n", len, buf);
        return ms->csock ? msrp_socket_send(ms->csock, buf, &len) : SWITCH_STATUS_FALSE;
 }
 
-#if 0
-SWITCH_STANDARD_APP(msrp_echo_function)
-{
-       msrp_session_t *msrp_session = NULL;
-       switch_msrp_msg_t *msrp_msg = NULL;
-       switch_channel_t *channel = switch_core_session_get_channel(session);
-       // private_object_t *tech_pvt = switch_core_session_get_private(session);
 
-       if (!tech_pvt) {
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No tech_pvt!\n");
-               return;
-       }
+SWITCH_DECLARE(switch_msrp_msg_t *) switch_msrp_msg_create()
+{
+       switch_msrp_msg_t *msg = malloc(sizeof(switch_msrp_msg_t));
+       switch_assert(msg);
 
-       if(!tech_pvt->msrp_session) {
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No msrp_session!\n");
-               return;
-       }
+       memset(msg, 0, sizeof(switch_msrp_msg_t));
+       switch_event_create(&msg->headers, SWITCH_EVENT_GENERAL);
+       switch_assert(msg->headers);
 
-       while (switch_channel_ready(channel) && (msrp_session = tech_pvt->msrp_session)) {
-               if ((msrp_msg = msrp_session_pop_msg(msrp_session)) == NULL) {
-                       switch_yield(100000);
-                       continue;
-               }
+       return msg;
+}
 
-               if (msrp_msg->method == MSRP_METHOD_SEND) { /*echo back*/
-                       char *p;
-                       p = msrp_msg->headers[MSRP_H_TO_PATH];
-                       msrp_msg->headers[MSRP_H_TO_PATH] = msrp_msg->headers[MSRP_H_FROM_PATH];
-                       msrp_msg->headers[MSRP_H_FROM_PATH] = p;
-                       msrp_send(msrp_session->socket, msrp_msg);
-               }
+SWITCH_DECLARE(switch_msrp_msg_t *) switch_msrp_msg_dup(switch_msrp_msg_t *msg)
+{
+       switch_msrp_msg_t *new_msg = malloc(sizeof(switch_msrp_msg_t));
+       switch_assert(new_msg);
+       memset(new_msg, 0, sizeof(switch_msrp_msg_t));
+       switch_event_dup(&new_msg->headers, msg->headers);
+       switch_assert(new_msg->headers);
 
-               switch_safe_free(msrp_msg);
-               msrp_msg = NULL;
+       new_msg->transaction_id = switch_msrp_msg_get_header(new_msg, MSRP_H_TRASACTION_ID);
+       new_msg->delimiter = switch_msrp_msg_get_header(new_msg, MSRP_H_DELIMITER);
+       new_msg->code_description = switch_msrp_msg_get_header(new_msg, MSRP_H_CODE_DESCRIPTION);
+       new_msg->state = msg->state;
+       new_msg->method = msg->method;
+       new_msg->code_number = msg->code_number;
+       new_msg->payload_bytes = msg->payload_bytes;
 
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "eat one message, left:%d\n", (int)msrp_session->msrp_msg_count);
+       if (msg->payload) {
+               memcpy(new_msg->payload, msg->payload, msg->payload_bytes);
        }
 
-       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Echo down!\n");
+       return new_msg;
+}
+
+SWITCH_DECLARE(void) switch_msrp_msg_destroy(switch_msrp_msg_t **msg)
+{
 
+       switch_msrp_msg_t *msrp_msg = *msg;
+       if (msrp_msg->headers) {
+               switch_event_destroy(&msrp_msg->headers);
+       }
+
+       switch_safe_free(msrp_msg->payload);
+       *msg = NULL;
 }
 
-SWITCH_STANDARD_APP(msrp_recv_function)
+/* Experimental */
+
+SWITCH_STANDARD_APP(msrp_recv_file_function)
 {
-       msrp_session_t *msrp_session = NULL;
+       switch_msrp_session_t *msrp_session = NULL;
        switch_msrp_msg_t *msrp_msg = NULL;
        switch_channel_t *channel = switch_core_session_get_channel(session);
-       private_object_t *tech_pvt = switch_core_session_get_private(session);
        switch_memory_pool_t *pool = switch_core_session_get_pool(session);
        switch_file_t *fd;
        const char *filename = data;
 
-       if (!tech_pvt) {
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No tech_pvt!\n");
-               return;
-       }
-
-       if(!tech_pvt->msrp_session) {
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No msrp_session!\n");
-               return;
-       }
+       switch_channel_set_flag(channel, CF_TEXT_PASSIVE);
+       switch_channel_answer(channel);
 
        if (zstr(data)) {
                filename = switch_channel_get_variable(channel, "sip_msrp_file_name");
+
                if (zstr(filename)) {
                        switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No file specified.\n");
                        return;
                }
+
                filename = switch_core_session_sprintf(session, "%s%s%s", SWITCH_GLOBAL_dirs.base_dir, SWITCH_PATH_SEPARATOR, filename);
        }
 
-       if (!(msrp_session = tech_pvt->msrp_session)) {
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Not a msrp session!\n");
+       if (!(msrp_session = switch_core_media_get_msrp_session(session))) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Not a MSRP session!\n");
                return;
        }
 
@@ -1495,57 +1585,50 @@ SWITCH_STANDARD_APP(msrp_recv_function)
                return;
        }
 
+       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "File [%s] Opened\n", filename);
+
        while (1) {
-               if ((msrp_msg = msrp_session_pop_msg(msrp_session)) == NULL) {
+               if ((msrp_msg = switch_msrp_session_pop_msg(msrp_session)) == NULL) {
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "MSRP message queue size: %d\n", (int)msrp_session->msrp_msg_count);
                        if (!switch_channel_ready(channel)) break;
-                       switch_yield(10000);
                        continue;
                }
 
                if (msrp_msg->method == MSRP_METHOD_SEND) {
                        switch_size_t bytes = msrp_msg->payload_bytes;
-                       char *msg = switch_str_nil(msrp_msg->headers[MSRP_H_MESSAGE_ID]);
-                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s %" SWITCH_SIZE_T_FMT "bytes writing\n", msg, bytes);
+                       const char *msg = switch_msrp_msg_get_header(msrp_msg, MSRP_H_MESSAGE_ID);
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "%s %" SWITCH_SIZE_T_FMT " bytes writing\n", msg, bytes);
                        switch_file_write(fd, msrp_msg->payload, &bytes);
-                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%" SWITCH_SIZE_T_FMT "bytes written\n", bytes);
+                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "%" SWITCH_SIZE_T_FMT " bytes written\n", bytes);
                        if (bytes != msrp_msg->payload_bytes) {
-                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "write fail, bytes lost!\n");
+                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "write failed, bytes lost!\n");
                        }
                }
 
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "eat one message, left:%d\n", (int)msrp_session->msrp_msg_count);
-
                switch_safe_free(msrp_msg);
        }
 
        switch_file_close(fd);
-       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "File closed!\n");
+       switch_channel_clear_flag(channel, CF_TEXT_PASSIVE);
+
+       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "File closed!\n");
 }
 
-SWITCH_STANDARD_APP(msrp_send_function)
+/* Experimental, if it doesn't work, it doesn't */
+
+SWITCH_STANDARD_APP(msrp_send_file_function)
 {
-       msrp_session_t *msrp_session = NULL;
+       switch_msrp_session_t *msrp_session = NULL;
        switch_msrp_msg_t *msrp_msg = NULL;
        switch_channel_t *channel = switch_core_session_get_channel(session);
-       private_object_t *tech_pvt = switch_core_session_get_private(session);
        switch_memory_pool_t *pool = switch_core_session_get_pool(session);
        switch_file_t *fd;
        const char *filename = data;
-       switch_size_t len = 2048;
-       char buf[2048];
+       switch_size_t len = 1024;
+       char buf[1024];
        int sanity = 10;
 
-       if (!tech_pvt) {
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No tech_pvt!\n");
-               return;
-       }
-
-       if(!tech_pvt->msrp_session) {
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No msrp_session!\n");
-               return;
-       }
-
-       if (!(msrp_session = tech_pvt->msrp_session)) {
+       if (!(msrp_session = switch_core_media_get_msrp_session(session))) {
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Not a msrp session!\n");
                return;
        }
@@ -1555,41 +1638,33 @@ SWITCH_STANDARD_APP(msrp_send_function)
                return;
        }
 
-       switch_assert(pool);
-
-       switch_zmalloc(msrp_msg, sizeof(switch_msrp_msg_t));
-       switch_assert(msrp_msg);
+       msrp_msg = switch_msrp_msg_create();
 
-       msrp_msg->headers[MSRP_H_FROM_PATH] = switch_mprintf("msrp://%s:%d/%s;tcp",
-               tech_pvt->rtpip, tech_pvt->msrp_session->local_port, tech_pvt->msrp_session->call_id);
-       msrp_msg->headers[MSRP_H_TO_PATH] = tech_pvt->msrp_session->remote_path;
-       /*TODO: send file in octet or maybe guess mime?*/
-       msrp_msg->headers[MSRP_H_CONTENT_TYPE] = "application/octet-stream";
-       msrp_msg->headers[MSRP_H_CONTENT_TYPE] = "text/plain";
+       switch_msrp_msg_add_header(msrp_msg, MSRP_H_CONTENT_TYPE, "text/plain");
 
-       msrp_msg->bytes = switch_file_get_size(fd);
+       msrp_msg->payload_bytes = switch_file_get_size(fd);
        msrp_msg->byte_start = 1;
 
-       while(sanity-- && tech_pvt->msrp_session->socket == NULL) {
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Waiting socket\n");
+       while(sanity-- && !msrp_session->running) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Waiting MSRP socket ...\n");
                switch_yield(1000000);
        }
 
-       if (tech_pvt->msrp_session->socket == NULL) {
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Waiting for socket timedout, exiting...\n");
+       if (!msrp_session->running) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Waiting for MSRP socket timedout, exiting...\n");
                goto end;
        }
 
        while (switch_file_read(fd, buf, &len) == SWITCH_STATUS_SUCCESS &&
-               switch_channel_ready(channel)) {
-               msrp_msg->payload = buf;
-               msrp_msg->byte_end = msrp_msg->byte_start + len - 1;
-               msrp_msg->payload_bytes = len;
+               switch_channel_ready(channel) && len > 0) {
+
+               msrp_msg->byte_end = msrp_msg->byte_start + len + 1;
+               switch_msrp_msg_set_payload(msrp_msg, buf, len);
 
                /*TODO: send in chunk should ending in + but not $ after delimiter*/
-               msrp_send(tech_pvt->msrp_session->socket, msrp_msg);
+               switch_msrp_send(msrp_session, msrp_msg);
 
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "%ld bytes sent\n", len);
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "%ld bytes sent\n", len);
 
                msrp_msg->byte_start += len;
        }
@@ -1602,97 +1677,8 @@ SWITCH_STANDARD_APP(msrp_send_function)
 
 end:
        switch_file_close(fd);
-
-       switch_safe_free(msrp_msg->headers[MSRP_H_FROM_PATH]);
-       switch_safe_free(msrp_msg);
-
-       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "File sent, closed!\n");
-}
-
-SWITCH_STANDARD_APP(msrp_bridge_function)
-{
-       switch_channel_t *caller_channel = switch_core_session_get_channel(session);
-       switch_core_session_t *peer_session = NULL;
-       switch_channel_t *peer_channel = NULL;
-       msrp_session_t *caller_msrp_session = NULL;
-       msrp_session_t *peer_msrp_session = NULL;
-       private_object_t *tech_pvt = NULL;
-       private_object_t *ptech_pvt = NULL;
-       switch_msrp_msg_t *msrp_msg = NULL;
-       switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
-       switch_status_t status;
-
-       if (zstr(data)) {
-               return;
-       }
-
-       if ((status =
-                switch_ivr_originate(session, &peer_session, &cause, data, 0, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL)) != SWITCH_STATUS_SUCCESS) {
-               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Originate Failed.  Cause: %s\n", switch_channel_cause2str(cause));
-               return;
-       }
-
-       switch_ivr_signal_bridge(session, peer_session);
-       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "msrp channel bridged\n");
-
-       peer_channel = switch_core_session_get_channel(session);
-       tech_pvt = switch_core_session_get_private(session);
-       ptech_pvt = switch_core_session_get_private(peer_session);
-
-       caller_msrp_session = tech_pvt->msrp_session;
-       peer_msrp_session = ptech_pvt->msrp_session;
-       switch_assert(caller_msrp_session);
-       switch_assert(peer_msrp_session);
-
-       if (switch_channel_test_flag(peer_channel, CF_ANSWERED) && !switch_channel_test_flag(caller_channel, CF_ANSWERED)) {
-               switch_channel_pass_callee_id(peer_channel, caller_channel);
-               switch_channel_answer(caller_channel);
-       }
-
-       // TODO we need to run the following code in a new thread
-       // TODO we cannot test channel_ready as we don't have (audio) media
-       // while (switch_channel_ready(caller_channel) && switch_channel_ready(peer_channel)){
-       while (switch_channel_get_state(caller_channel) == CS_HIBERNATE &&
-               switch_channel_get_state(peer_channel) == CS_HIBERNATE){
-               int found = 0;
-               if ((msrp_msg = msrp_session_pop_msg(caller_msrp_session))) {
-                       if (msrp_msg->method == MSRP_METHOD_SEND) { /* write to peer */
-                               msrp_msg->headers[MSRP_H_FROM_PATH] = switch_mprintf("msrp://%s:%d/%s;tcp",
-                                       ptech_pvt->rtpip, peer_msrp_session->local_port, peer_msrp_session->call_id);
-                               msrp_msg->headers[MSRP_H_TO_PATH] = peer_msrp_session->remote_path;
-
-                               if (peer_msrp_session->socket) {
-                                       msrp_send(peer_msrp_session->socket, msrp_msg);
-                               } else {
-                                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "socket not ready, discarding one message!!\n");
-                               }
-                       }
-                       switch_safe_free(msrp_msg);
-                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "eat one message, left:%d\n", (int)caller_msrp_session->msrp_msg_count);
-                       found++;
-               }
-
-               if ((msrp_msg = msrp_session_pop_msg(peer_msrp_session))) {
-                       if (msrp_msg->method == MSRP_METHOD_SEND) { /* write to caller */
-                               msrp_msg->headers[MSRP_H_FROM_PATH] = switch_mprintf("msrp://%s:%d/%s;tcp",
-                                       tech_pvt->rtpip, caller_msrp_session->local_port, caller_msrp_session->call_id);
-                               msrp_msg->headers[MSRP_H_TO_PATH] = caller_msrp_session->remote_path;
-                               msrp_send(caller_msrp_session->socket, msrp_msg);
-                       }
-                       switch_safe_free(msrp_msg);
-                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "eat one message, left:%d\n", (int)peer_msrp_session->msrp_msg_count);
-                       found++;
-               }
-
-               msrp_msg = NULL;
-               if (!found) switch_yield(100000);
-       }
-
-       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Bridge down!\n");
-
-       if (peer_session) {
-               switch_core_session_rwunlock(peer_session);
-       }
+       switch_msrp_msg_destroy(&msrp_msg);
+       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "File [%s] sent, closed!\n", filename);
 }
 
 SWITCH_STANDARD_API(uuid_msrp_send_function)
@@ -1700,10 +1686,8 @@ SWITCH_STANDARD_API(uuid_msrp_send_function)
        char *mycmd = NULL, *argv[3] = { 0 };
        int argc;
        switch_core_session_t *msession = NULL;
-       // msrp_session_t *msrp_session = NULL;
+       switch_msrp_session_t *msrp_session = NULL;
        switch_msrp_msg_t *msrp_msg = NULL;
-       private_object_t *tech_pvt = NULL;
-       switch_memory_pool_t *pool = NULL;
 
        if (zstr(cmd) || !(mycmd = strdup(cmd))) {
                goto error;
@@ -1720,46 +1704,26 @@ SWITCH_STANDARD_API(uuid_msrp_send_function)
                return SWITCH_STATUS_SUCCESS;
        }
 
-       tech_pvt = switch_core_session_get_private(msession);
-       pool = switch_core_session_get_pool(msession);
-       switch_assert(pool);
-
-       if (!tech_pvt) {
-               stream->write_function(stream, "-ERR No tech_pvt.\n");
-               switch_core_session_rwunlock(msession);
-               return SWITCH_STATUS_SUCCESS;
-       }
-
-       if(!tech_pvt->msrp_session) {
+       if (!(msrp_session = switch_core_media_get_msrp_session(msession))) {
                stream->write_function(stream, "-ERR No msrp_session.\n");
                switch_core_session_rwunlock(msession);
                return SWITCH_STATUS_SUCCESS;
        }
 
-       switch_zmalloc(msrp_msg, sizeof(switch_msrp_msg_t));
-       switch_assert(msrp_msg);
-
-       msrp_msg->headers[MSRP_H_FROM_PATH] = switch_mprintf("msrp://%s:%d/%s;tcp",
-               tech_pvt->rtpip, tech_pvt->msrp_session->local_port, tech_pvt->msrp_session->call_id);
-       msrp_msg->headers[MSRP_H_TO_PATH] = tech_pvt->msrp_session->remote_path;
-       msrp_msg->headers[MSRP_H_CONTENT_TYPE] = "text/plain";
-       msrp_msg->payload = switch_core_strdup(pool, argv[1]);
-
-       msrp_send(tech_pvt->msrp_session->socket, msrp_msg);
-
-       switch_safe_free(msrp_msg->headers[MSRP_H_FROM_PATH]);
-       switch_safe_free(msrp_msg);
-       stream->write_function(stream, "+OK sent\n");
+       msrp_msg = switch_msrp_msg_create();
+       switch_msrp_msg_add_header(msrp_msg, MSRP_H_CONTENT_TYPE, "text/plain");
+       switch_msrp_msg_set_payload(msrp_msg, argv[1], strlen(argv[1]));
+       switch_msrp_send(msrp_session, msrp_msg);
+       switch_msrp_msg_destroy(&msrp_msg);
+       stream->write_function(stream, "+OK message sent\n");
        switch_core_session_rwunlock(msession);
        return SWITCH_STATUS_SUCCESS;
+
 error:
        stream->write_function(stream, "-ERR Usage: uuid_msrp_send <uuid> msg\n");
        return SWITCH_STATUS_SUCCESS;
 }
 
-#endif
-
-
 #define MSRP_SYNTAX "debug <on|off>|restart"
 SWITCH_STANDARD_API(msrp_api_function)
 {
@@ -1784,22 +1748,19 @@ SWITCH_STANDARD_API(msrp_api_function)
 
 SWITCH_DECLARE(void) switch_msrp_load_apis_and_applications(switch_loadable_module_interface_t **module_interface)
 {
-       // switch_application_interface_t *app_interface;
+       switch_application_interface_t *app_interface;
        switch_api_interface_t *api_interface;
 
-       SWITCH_ADD_API(api_interface, "msrp", "MSRP Functions", msrp_api_function, "JSON");
+       SWITCH_ADD_API(api_interface, "msrp", "MSRP Functions", msrp_api_function, MSRP_SYNTAX);
 
-#if 0
-       SWITCH_ADD_API(api_interface, "uuid_msrp_send", "send msrp text", uuid_msrp_send_function, "<cmd> <args>");
-       SWITCH_ADD_APP(app_interface, "msrp_echo", "Echo msrp message", "Perform an echo test against the msrp channel", msrp_echo_function, "", SAF_NONE);
-       SWITCH_ADD_APP(app_interface, "msrp_recv", "Recv msrp message to file", "Recv msrp message", msrp_recv_function, "<filename>", SAF_NONE);
-       SWITCH_ADD_APP(app_interface, "msrp_send", "Send file via msrp", "Send file via msrp", msrp_send_function, "<filename>", SAF_NONE);
-       SWITCH_ADD_APP(app_interface, "msrp_bridge", "Bridge msrp channels", "Bridge msrp channels", msrp_bridge_function, "dialstr", SAF_NONE);
-#endif
+       SWITCH_ADD_API(api_interface, "uuid_msrp_send", "send msrp text", uuid_msrp_send_function, "<msg>");
+       SWITCH_ADD_APP(app_interface, "msrp_recv_file", "Recv msrp message to file", "Recv msrp message", msrp_recv_file_function, "<filename>", SAF_SUPPORT_TEXT_ONLY | SAF_SUPPORT_NOMEDIA);
+       SWITCH_ADD_APP(app_interface, "msrp_send_file", "Send file via msrp", "Send file via msrp", msrp_send_file_function, "<filename>", SAF_SUPPORT_TEXT_ONLY | SAF_SUPPORT_NOMEDIA);
 
        switch_console_set_complete("add msrp debug on");
        switch_console_set_complete("add msrp debug off");
        switch_console_set_complete("restart");
+       switch_console_set_complete("add uuid_msrp_send ::console::list_uuid");
 }