[Asterisk-code-review] Add the ability to read the media file type from HTTP header... (asterisk[15])

Sean Bright asteriskteam at digium.com
Wed Feb 14 08:02:19 CST 2018


Sean Bright has uploaded this change for review. ( https://gerrit.asterisk.org/8209


Change subject: Add the ability to read the media file type from HTTP header for playback
......................................................................

Add the ability to read the media file type from HTTP header for playback

How it works today:
media_cache tries to parse out the extension of the media file to be played
from the URI provided to Asterisk while caching the file.

What's expected:
Better will be to have Asterisk get extension from other ways too. One of the
common ways is to get the type of content from the CONTENT-TYPE header in the
HTTP response for fetching the media file using the URI provided.

Steps to Reproduce:
Provide a URL of the form: http://host/media/1234 to Asterisk for media
playback. It fails to play and logs show the following error line:

[Sep 15 15:48:05] WARNING [29148] [C-00000092] file.c:
File http://host/media/1234 does not exist in any format

Scenario this issue is blocking:
In the case where the media files are stored in some cloud object store,
following can block the media being played via Asterisk:

Cloud storage generally needs authenticated access to the storage. The way
to do that is by using signed URIs. With the signed URIs there's no way to
preserve the name of the file.
In most cases Cloud storage returns a key to access the object and preserving
file name is also not a thing there

ASTERISK-27286

 Reporter: Gaurav Khurana

Change-Id: I1b14692a49b2c1ac67688f58757184122e92ba89
---
M formats/format_pcm.c
M formats/format_vox.c
M formats/format_wav.c
M include/asterisk/file.h
M include/asterisk/mod_format.h
M main/bucket.c
M main/file.c
M main/format_cap.c
M main/media_cache.c
M res/res_http_media_cache.c
10 files changed, 96 insertions(+), 8 deletions(-)



  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/09/8209/1

diff --git a/formats/format_pcm.c b/formats/format_pcm.c
index 35612c9..ec6f82b 100644
--- a/formats/format_pcm.c
+++ b/formats/format_pcm.c
@@ -498,6 +498,7 @@
 static struct ast_format_def pcm_f = {
 	.name = "pcm",
 	.exts = "pcm|ulaw|ul|mu|ulw",
+	.mime_types = "audio/basic",
 	.write = pcm_write,
 	.seek = pcm_seek,
 	.trunc = pcm_trunc,
diff --git a/formats/format_vox.c b/formats/format_vox.c
index b63e225..023c409 100644
--- a/formats/format_vox.c
+++ b/formats/format_vox.c
@@ -128,6 +128,7 @@
 static struct ast_format_def vox_f = {
 	.name = "vox",
 	.exts = "vox",
+	.mime_types = "audio/x-vox",
 	.write = vox_write,
 	.seek = vox_seek,
 	.trunc = vox_trunc,
diff --git a/formats/format_wav.c b/formats/format_wav.c
index 81a686e..ec7e3d3 100644
--- a/formats/format_wav.c
+++ b/formats/format_wav.c
@@ -532,6 +532,7 @@
 static struct ast_format_def wav_f = {
 	.name = "wav",
 	.exts = "wav",
+	.mime_types = "audio/wav|audio/x-wav",
 	.open =	wav_open,
 	.rewrite = wav_rewrite,
 	.write = wav_write,
diff --git a/include/asterisk/file.h b/include/asterisk/file.h
index c17cb32..a5bd147 100644
--- a/include/asterisk/file.h
+++ b/include/asterisk/file.h
@@ -427,6 +427,26 @@
  */
 struct ast_format *ast_get_format_for_file_ext(const char *file_ext);
 
+/*!
+ * \brief Get the extensions associated with the given MIME TYPE
+ *
+ * \param file_ext The file extension for which to find the format
+ *
+ * \retval NULL if not found
+ * \retval A pointer to the ast_format associated with this file extension
+ */
+
+int ast_get_extensions_for_mime_type(const char *mime_type, char *exts);
+
+/*!
+ * \brief Check if the file extension is a supported extension
+ *
+ * \param file_ext The file extension for which to find the format
+ *
+ * \retval 1 if not supported
+ * \retval 0 if supported
+ */
+int ast_is_file_ext_supported(const char *file_ext);
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif
diff --git a/include/asterisk/mod_format.h b/include/asterisk/mod_format.h
index 5f93ea4..6e772f0 100644
--- a/include/asterisk/mod_format.h
+++ b/include/asterisk/mod_format.h
@@ -44,6 +44,7 @@
 	char name[80];		/*!< Name of format */
 	char exts[80];		/*!< Extensions (separated by | if more than one)
 						 * this format can read.  First is assumed for writing (e.g. .mp3) */
+	char mime_types[80]; /*!< MIME Types related to the format (separated by | if more than one)*/
 	struct ast_format *format;	/*!< Format of frames it uses/provides (one only) */
 	/*!
 	 * \brief Prepare an input stream for playback.
diff --git a/main/bucket.c b/main/bucket.c
index 07cd016..8a6107e 100644
--- a/main/bucket.c
+++ b/main/bucket.c
@@ -905,7 +905,6 @@
 	if (fd < 0) {
 		return -1;
 	}
-
 	close(fd);
 	return 0;
 }
diff --git a/main/file.c b/main/file.c
index 41131f9..3bc5daf 100644
--- a/main/file.c
+++ b/main/file.c
@@ -347,6 +347,22 @@
 	return 0;
 }
 
+/* compare type against the list 'mime_types' */
+/* XXX need a better algorithm */
+static int mime_types_compare(const char *mime_types, const char *type)
+{
+	char tmp[256];
+	char *stringp = tmp, *mime_type;
+
+	ast_copy_string(tmp, mime_types, sizeof(tmp));
+	while ((mime_type = strsep(&stringp, "|"))) {
+		if (!strcmp(mime_type, type))
+			return 1;
+	}
+
+	return 0;
+}
+
 /*!
  * \internal
  * \brief Close the file stream by canceling any pending read / write callbacks
@@ -1920,6 +1936,33 @@
 	return NULL;
 }
 
+int ast_get_extensions_for_mime_type(const char *mime_type, char *exts)
+{
+	struct ast_format_def *f;
+	SCOPED_RDLOCK(lock, &formats.lock);
+	AST_RWLIST_TRAVERSE(&formats, f, list) {
+		if (mime_types_compare(f->mime_types, mime_type)) {
+			if (exts){
+				ast_copy_string(exts, f->exts, strlen(f->exts) + 1);
+				return 0;
+			}
+		}
+	}
+
+	return 1;
+}
+int ast_is_file_ext_supported(const char *file_ext)
+{
+	struct ast_format_def *f;
+	SCOPED_RDLOCK(lock, &formats.lock);
+	AST_RWLIST_TRAVERSE(&formats, f, list) {
+		if (exts_compare(f->exts, file_ext)) {
+            return 0;
+		}
+	}
+
+	return 1;
+}
 static struct ast_cli_entry cli_file[] = {
 	AST_CLI_DEFINE(handle_cli_core_show_file_formats, "Displays file formats")
 };
diff --git a/main/format_cap.c b/main/format_cap.c
index d71ccdb..081c4fd 100644
--- a/main/format_cap.c
+++ b/main/format_cap.c
@@ -623,7 +623,6 @@
 			return 1;
 		}
 	}
-
 	return 0;
 }
 
diff --git a/main/media_cache.c b/main/media_cache.c
index 90057dc..42193d5 100644
--- a/main/media_cache.c
+++ b/main/media_cache.c
@@ -35,6 +35,7 @@
 #include "asterisk/bucket.h"
 #include "asterisk/astdb.h"
 #include "asterisk/cli.h"
+#include "asterisk/file.h"
 #include "asterisk/media_cache.h"
 
 /*! The name of the AstDB family holding items in the cache. */
@@ -142,10 +143,33 @@
 	} else if (!strchr(bucket_file->path, '.') && (ext = strrchr(ast_sorcery_object_get_id(bucket_file), '.'))) {
 		/* If we don't have a file extension and were provided one in the URI, use it */
 		char new_path[PATH_MAX];
-
+		char temp_ext[PATH_MAX];
+		strcpy(temp_ext, ext);
+		/*Don't pass '.' while checking for supported extension*/
+		if (ast_is_file_ext_supported(ext + 1)){
+			/* If the file extension passed in the URI isn't supported check for the
+			 * extension based on the MIME TYPE passed in CONTENT_TYPE header before
+			 * giving up
+			 * If a match is found then retrieve the extension from the supported list corresponding
+			 * to the mime-type and use that to rename the file*/
+			struct ast_bucket_metadata *header = ast_bucket_file_metadata_get(bucket_file, "content-type");
+			if (header != NULL) {
+				const char *mime_type = header->value;
+				char *exts = ast_malloc(sizeof(char) * PATH_MAX);
+				if (!ast_get_extensions_for_mime_type(mime_type, exts)){
+					/*Pick the first extension that matches the mime-type*/
+					char *tmp = strsep(&exts, "|");
+					
+					/*Not updating the original ext here to keep the key for media-cache same*/
+					snprintf(temp_ext, strlen(temp_ext), ".%s", tmp);
+				}
+				
+				ast_free(exts);
+			}
+		}
+        
 		ast_bucket_file_metadata_set(bucket_file, "ext", ext);
-
-		snprintf(new_path, sizeof(new_path), "%s%s", bucket_file->path, ext);
+		snprintf(new_path, sizeof(new_path), "%s%s", bucket_file->path, temp_ext);
 		rename(bucket_file->path, new_path);
 		ast_copy_string(bucket_file->path, new_path, sizeof(bucket_file->path));
 	}
@@ -175,7 +199,7 @@
 				*ext = '\0';
 			}
 			ao2_ref(bucket_file, -1);
-
+			
 			ast_debug(5, "Returning media at local file: %s\n", file_path);
 			return 0;
 		}
@@ -206,7 +230,6 @@
 	}
 	ao2_link_flags(media_cache, bucket_file, OBJ_NOLOCK);
 	ao2_ref(bucket_file, -1);
-
 	ast_debug(5, "Returning media at local file: %s\n", file_path);
 
 	return 0;
@@ -296,7 +319,6 @@
 
 	snprintf(tmp, sizeof(tmp), "%jd", (intmax_t)st.st_size);
 	ast_bucket_file_metadata_set(bucket_file, "size", tmp);
-
 	ext = strrchr(file_path_ptr, '.');
 	if (ext) {
 		ast_bucket_file_metadata_set(bucket_file, "ext", ext + 1);
diff --git a/res/res_http_media_cache.c b/res/res_http_media_cache.c
index 918686e..c3680d8 100644
--- a/res/res_http_media_cache.c
+++ b/res/res_http_media_cache.c
@@ -84,6 +84,7 @@
 	if (strcasecmp(header, "ETag")
 		&& strcasecmp(header, "Cache-Control")
 		&& strcasecmp(header, "Last-Modified")
+		&& strcasecmp(header, "Content-Type")
 		&& strcasecmp(header, "Expires")) {
 		return realsize;
 	}

-- 
To view, visit https://gerrit.asterisk.org/8209
To unsubscribe, visit https://gerrit.asterisk.org/settings

Gerrit-Project: asterisk
Gerrit-Branch: 15
Gerrit-MessageType: newchange
Gerrit-Change-Id: I1b14692a49b2c1ac67688f58757184122e92ba89
Gerrit-Change-Number: 8209
Gerrit-PatchSet: 1
Gerrit-Owner: Sean Bright <sean.bright at gmail.com>
Gerrit-Reviewer: Gaurav Khurana <gkhurana at godaddy.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20180214/f5de1d38/attachment-0001.html>


More information about the asterisk-code-review mailing list