BITS proxy in minutest details
Background Intelligent Transfer Service - сложная и заковыристая часть Windows. Сложная она потому, что малоизвестная, малоиспользуемая простыми пользователями, слабо документированная и при этом я насчитал уже 5 ее версий! Думаю, основная причина ее создания - Windows Update. Она же - основная причина появления новых версий и такого программного интерфейса, как мы имеем сйечас.
Недавно я разбирался с настройками proxy для задачи, которые задаются методом IBackgroundCopyJob::SetProxySettings
. Из документации можно предположить, что в параметр pProxyList
можно передать сроку следующего вида: [protocol=][protocol://]server[:port] [protocol=][protocol://]server[:port] ...
. О точном формате строки и о реакции на нее самой службой не сказано ничегошеньки. Пришлось потратить прядочно времени на вскрытие черного ящика.
Мое исследование началось с двух вещей:
- Включить информативное логирование Background Intelligent Transfer Service
- Включить логирование WinHTTP (а именно ее использует Background Intelligent Transfer Service начиная с версии 2.0)
Как это сделать описано здесь.
set tracing output=file trace-file-prefix=D:\Development\Logs\BITS\ level=default format=ansi max-trace-file-size=512000000 state=enabled
Единственный нюанс, для того, чтобы логирование службы заработало, - необходимо перегрузить машину.
Как Background Intelligent Transfer Service разбирает строку proxy
Строка делится на части (назову proxy item) по разделителю " " (пробел). Далее, по порядку BITS проверяет, можно ли использовать proxy item для текущего файла. Если да - передает управление WinHTTP, установив proxy item в качестве строки proxy (см. структуру WINHTTP_PROXY_INFO
- ничего не напоминает?). Если скачать файл не удалось, служба с радостью переходит к следующему proxy item, а если они закончились - получаем BG_JOB_STATE_TRANSIENT_ERROR
. А вот если proxy item каким-то образом файлу не подошел - начинается самодеятельность: BITS пытается использовать режим BG_JOB_PROXY_USAGE_AUTODETECT
, а если и с этим пролет - качает напрямую (BG_JOB_PROXY_USAGE_NO_PROXY
)!
Судя по всему, не подошел
- это если протокол proxy item не совпадает с протоколом файла. В результате, если строка прокси будет https://someproxy somegenericproxy
или x=y http://someproxy somegenericproxy
, то файл по протоколу http
не будет качаться через somegenericproxy
или someproxy
!
Выводы напрашиваются следующие:
- Можно указать много proxy серверов и служба будет пробовать их в порядке следования.
- Служба может отказаться от использования proxy сервера.
- Мусор в строке
pProxyList
автоматически ведет к предыдущему пункту. - Желательно не использовать префикс протокола в элементах строки (использовать протоколонезависимые proxy сервера).
Тем более, если задача состоит из файлов с разными протоколами загрузки.
https=...
не подходит файламhttp://...
, аhttp=...
- файламhttps://...
. Поэтому, часть файлов будет гарантированно качаться в обход proxy.Здесь, правда, можно обмануть BITS - воспользоваться тем, что есть еще один пробельный разделитель -
\t
(TAB). Если строкаpProxyList
выглядит, как\thttp=http_proxy1\thttps=https_proxy1 \thttp=http_proxy2\thttps=https_proxy2
, то в качестве строки proxy в WinHTTP попадет сначала\thttp=http_proxy1\thttps=https_proxy1
, а если произошла ошибка, то после и\thttp=http_proxy2\thttps=https_proxy2
. А хитрость в том, что WinHTTP считает\t
пробелом и выберет нужный сервер с учетом протокола. Использовать этот метод я не рекомендую, т.к. оно может поломаться с очередным пакетом обновлений. Да и не известно, как это будет работать с другими версиями службы (у меня 3.0 на Windows Vista) и не с WinHTTP, которую Background Intelligent Transfer Service начала использовать только с версии 2.0!