icecast relay и редиректы

Сервер icecast может использоваться не только для организации вещания новых сетевых медиапотоков, но и для ретрансляции уже существующих. Источник исходного потока при этом может являться распределенной структурой других icecast-подобных серверов, в которых для распределения нагрузки на головном сервере может использоваться простой http-редирект (код 302) на дополнительные узлы.

Хотя relay-функциональность icecast и позволяет разбирать этот код и реагировать на него соответствующим образом, работает это не всегда.

Можно столкнуться со следующей ситуацией: головной source-сервер перегружен и выдает редиректы на дополнительные серверы, при проверке браузером все корректно, но наш icecast-ретранслятор их будто “не замечает” и выдает клиентам ошибку 404. В логах нашего icecast’а при этом можно увидеть следующие записи:

[2015-09-25  10:58:40] INFO slave/start_relay_stream Starting relayed source at mountpoint "/<mountname>"
[2015-09-25  10:58:40] INFO slave/open_relay_connection connecting to <main.source>:80
[2015-09-25  10:58:40] INFO slave/open_relay_connection redirect received HTTP://<fallback.source>

После этого клиенту выдается ошибка 404 и более ничего содержательного в лог не попадает. Так в чем же дело?

В исходном коде icecast можно найти следующие строки:

            ICECAST_LOG_INFO("redirect received %s", uri);
            if (strncmp (uri, "http://", 7) != 0)
                break;

Так выясняется, что если полученная ссылка из 302-го редиректа не начинается на “http://” (в НИЖНЕМ регистре!), то наш icecast с ней не будет делать вообще ничего и сделает вид, что никакого редиректа не было. А как видно из лога, наш источник рассылает редиректы, начинающиеся на HTTP:// в верхнем регистре.

Очевидно, надо научить icecast не обращать внимание на разницу регистров в протоколе. Это можно сделать разными способами, оптимальность и красота которых зависит от качества вашего владения кунг-фу Си. Можно, например, сделать как-то так:

--- icecast-2.4.2/src/slave.c   2015-04-08 11:06:13.000000000 +0300
+++ icecast-2.4.2-mod/src/slave.c       2015-09-25 10:55:29.495738535 +0300
@@ -238,13 +238,19 @@
         if (strcmp (httpp_getvar (parser, HTTPP_VAR_ERROR_CODE), "302") == 0)
         {
             /* better retry the connection again but with different details */
-            const char *uri, *mountpoint;
-            int len;
+            const char *uri, *mountpoint, *proc = "http://";
+            int i, len;

             uri = httpp_getvar (parser, "location");
+
             ICECAST_LOG_INFO("redirect received %s", uri);
-            if (strncmp (uri, "http://", 7) != 0)
-                break;
+            for (i = 0; i < 7 && uri[i]; i++) {
+                if ((tolower(uri[i]) - tolower(proc[i])) != 0) {
+                    i = 10;
+                    break;
+                }
+            }
+            if (i == 10) break;
             uri += 7;
             mountpoint = strchr (uri, '/');
             free (mount);

Пересобираем, подключаемся, смотрим лог:

[2015-09-25  11:08:40] INFO slave/start_relay_stream Starting relayed source at mountpoint "/<mountname>"
[2015-09-25  11:08:40] INFO slave/open_relay_connection connecting to <main.source>:80
[2015-09-25  11:08:40] INFO slave/open_relay_connection redirect received HTTP://<fallback.source>
[2015-09-25  11:08:40] INFO slave/open_relay_connection connecting to <fallback.source>:80
[2015-09-25  11:08:40] WARN format/format_get_type Unsupported or legacy stream type: "audio/mpeg". Falling back to generic minimal handler for best effort.
[2015-09-25  11:08:40] INFO source/source_main listener count on /<mountname> now 1

И все работает.

This entry was posted in Сеть и интернет and tagged , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>