From 08603c7e89bdb91f40b8910782f6f7f3d67dbc39 Mon Sep 17 00:00:00 2001 From: Seven Du Date: Mon, 2 Jan 2017 10:41:37 +0800 Subject: [PATCH] FS-9904 #resolve cleanup and refactor msrp --- src/include/switch_msrp.h | 29 +- src/mod/endpoints/mod_sofia/mod_sofia.c | 56 +- src/switch_core_media.c | 2 +- src/switch_msrp.c | 665 +++++++++++------------- 4 files changed, 360 insertions(+), 392 deletions(-) diff --git a/src/include/switch_msrp.h b/src/include/switch_msrp.h index 101f87178a..25f51e954c 100644 --- a/src/include/switch_msrp.h +++ b/src/include/switch_msrp.h @@ -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__) diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index c988cee5bc..a8299fe16d 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -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; + + if (msrp_msg) { + msrp_h_content_type = switch_msrp_msg_get_header(msrp_msg, MSRP_H_CONTENT_TYPE); + } 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); - } -#endif - 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 }; + switch_msrp_msg_t *msrp_msg = switch_msrp_msg_create(); + switch_status_t status = SWITCH_STATUS_SUCCESS; - //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_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; diff --git a/src/switch_core_media.c b/src/switch_core_media.c index ca5fce75a7..bcc7c2861d 100644 --- a/src/switch_core_media.c +++ b/src/switch_core_media.c @@ -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); } } diff --git a/src/switch_msrp.c b/src/switch_msrp.c index 8009f8a88d..81c9cd0638 100644 --- a/src/switch_msrp.c +++ b/src/switch_msrp.c @@ -34,7 +34,7 @@ #include #include -#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; } + switch_assert(p == buf + MSRP_BUFF_SIZE); + /* 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); - } + 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) + +SWITCH_DECLARE(switch_msrp_msg_t *) switch_msrp_msg_create() { - 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_msrp_msg_t *msg = malloc(sizeof(switch_msrp_msg_t)); + switch_assert(msg); - 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; - } - - 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; - } - - 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_safe_free(msrp_msg); - msrp_msg = NULL; - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "eat one message, left:%d\n", (int)msrp_session->msrp_msg_count); - } - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Echo down!\n"); + memset(msg, 0, sizeof(switch_msrp_msg_t)); + switch_event_create(&msg->headers, SWITCH_EVENT_GENERAL); + switch_assert(msg->headers); + return msg; } -SWITCH_STANDARD_APP(msrp_recv_function) +SWITCH_DECLARE(switch_msrp_msg_t *) switch_msrp_msg_dup(switch_msrp_msg_t *msg) { - msrp_session_t *msrp_session = NULL; + 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); + + 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; + + if (msg->payload) { + memcpy(new_msg->payload, msg->payload, msg->payload_bytes); + } + + 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; +} + +/* Experimental */ + +SWITCH_STANDARD_APP(msrp_recv_file_function) +{ + 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); + msrp_msg = switch_msrp_msg_create(); - switch_zmalloc(msrp_msg, sizeof(switch_msrp_msg_t)); - switch_assert(msrp_msg); + switch_msrp_msg_add_header(msrp_msg, MSRP_H_CONTENT_TYPE, "text/plain"); - 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"; - - 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 msg\n"); return SWITCH_STATUS_SUCCESS; } -#endif - - #define MSRP_SYNTAX "debug |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, " "); - 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, "", SAF_NONE); - SWITCH_ADD_APP(app_interface, "msrp_send", "Send file via msrp", "Send file via msrp", msrp_send_function, "", 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, ""); + SWITCH_ADD_APP(app_interface, "msrp_recv_file", "Recv msrp message to file", "Recv msrp message", msrp_recv_file_function, "", 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, "", 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"); }