Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] Pass mpd URL custom headers to actual video files? #20

Closed
matthuisman opened this issue Apr 12, 2017 · 7 comments · Fixed by #25
Closed

[Feature Request] Pass mpd URL custom headers to actual video files? #20

matthuisman opened this issue Apr 12, 2017 · 7 comments · Fixed by #25

Comments

@matthuisman
Copy link
Contributor

matthuisman commented Apr 12, 2017

I have a .strm file like this:

#KODIPROP:inputstreamaddon=inputstream.adaptive
#KODIPROP:inputstream.adaptive.manifest_type=mpd
#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha
#KODIPROP:inputstream.adaptive.license_key=https://wvlic.brightcove.com/proxy/5375730767001|Content-Type=application%2Fx-www-form-urlencoded&X-Forwarded-For=202.89.4.222|A{SSM}|
http://dashtvnz-a.akamaihd.net/963482467001/963482467001_5375755467001_5375730767001.mpd?pubId=963482467001&videoId=5375730767001|X-Forwarded-For=202.89.4.222

For a GEO blocked service.

Here's the log:
https://pastebin.com/raw/T8jsHLXV

You can see it get's the license all OK etc.
However, it fails to open http://dashtvnz-a.akamaihd.net/963482467001/5375755266001/video/1/init.mp4

This will be due to CURL not setting the X-Forwarded-For (it only sets keep alive)

Would it be possible to update the code to pass on any custom stream headers to the actual video files?

I guess somewhere around here it would happen:
https://github.com/peak3d/inputstream.adaptive/blob/master/src/main.cpp#L217

@matthuisman matthuisman changed the title .mpd Headers not passed down to mp4 files URL headers not passed down to mp4 files Apr 12, 2017
@matthuisman matthuisman changed the title URL headers not passed down to mp4 files [Feature Request] Pass mpd URL custom headers to actual video files? Apr 12, 2017
@matthuisman
Copy link
Contributor Author

matthuisman commented Apr 17, 2017

Possibly it could be an extra Addon Setting if that's easier to implement?
"Extra Headers" or something like that?
Then that download function (lines 189 & 214) just appends |{headers} to the end of the URL string?

xbmc->CURLCreate(url + "|" + xbmc->GetSetting("EXTRAHEADERS", (char*)&buf));

Pretty sure the CurlCreate takes care of splitting the string on | and parsing the headers?

@matthuisman
Copy link
Contributor Author

The downside to above is that add-ons like the one I write won't be able to set the extra headers.

@glennguy
Copy link
Contributor

glennguy commented Apr 27, 2017

@matthuisman It seems to be able to do this already, I think you need to URL encode the string properly - '&' should be '%2F'. i.e

#KODIPROP:inputstream.adaptive.license_key=https://wvlic.brightcove.com/proxy/5375730767001|Content-Type=application%2Fx-www-form-urlencoded%2FX-Forwarded-For=202.89.4.222|A{SSM}|

@matthuisman
Copy link
Contributor Author

matthuisman commented Apr 27, 2017

@glennguy

That's not quite the issue (the license key actually works fine)

The issue is that the X-Forwarded-For at the end of the MPD URL is not passed onto the actual video (init.mp4 / seg-1.m4f etc etc) files.

  1. The code fetches the MPD file correctly using the X-Forward
  2. The code get's the actual video files from the MPD file (eg. init.mp4)
  3. The code does not add X-Forward when requesting these video files

If you see my log here:
https://pastebin.com/B8L3gYK8

You can see CURL adding the custom header for the MPD & key URLS.
However, it doesn't add the custom header for any further files (init.mp4 etc) - it only adds a "keep-alive" header.

So I thought the code could store the custom headers in a variable when first fetching the MPD file.
Then these headers are just appended to any further URLS.

If it worked correctly, you should be able to play that STRM from my first post even though it's region locked to New Zealand :)

@glennguy
Copy link
Contributor

@matthuisman my bad, I did a pretty bad job of reading your first post.

I've made a fix that pretty much follows your suggestion of storing the headers in a variable and append them to segment downloads. It works for your strm file. It's an easy but probably not ideal implementation. I'll make a PR.

@matthuisman
Copy link
Contributor Author

@glennguy
You are a LEGEND!

You could also append the X-Forward headers in your Aussie add-ons so us Kiwis can use them :)

@matthuisman
Copy link
Contributor Author

Going to close this issue and continue convo on pull request :)

dobo90 added a commit to dobo90/inputstream.adaptive that referenced this issue Feb 8, 2023
* Add sleep inside AdaptiveTree.cpp to trigger the issue

From Kodi logs:

2023-02-08 18:02:11.679 T:22020    info <general>: Creating InputStream
2023-02-08 18:02:11.691 T:22020    info <general>: AddOnLog: inputstream.adaptive: [Repr. chooser] Resolution set: 4096x2304, max allowed: 8152x4436, Adjust refresh rate: 0
2023-02-08 18:02:11.989 T:22020    info <general>: AddOnLog: inputstream.adaptive: Successfully parsed manifest file (Periods: 1, Streams in first period: 2, Type: live)
2023-02-08 18:02:12.989 T:22024   error <general>: AddOnLog: inputstream.adaptive: SegmentUpdateWorker: DEBUG before RefreshLiveSegments()
2023-02-08 18:02:13.028 T:22020    info <general>: Creating Demuxer
2023-02-08 18:02:13.029 T:22020    info <general>: Opening stream: 1006 source: 256
2023-02-08 18:02:13.114 T:22024   error <general>: AddOnLog: inputstream.adaptive: SegmentUpdateWorker: DEBUG after RefreshLiveSegments()
2023-02-08 18:02:13.160 T:22020   error <general>: AddOnLog: inputstream.adaptive: DEBUG before sleep()
2023-02-08 18:02:14.114 T:22024   error <general>: AddOnLog: inputstream.adaptive: SegmentUpdateWorker: DEBUG before RefreshLiveSegments()
2023-02-08 18:02:14.135 T:22024   error <general>: AddOnLog: inputstream.adaptive: SegmentUpdateWorker: DEBUG after RefreshLiveSegments()
2023-02-08 18:02:15.135 T:22024   error <general>: AddOnLog: inputstream.adaptive: SegmentUpdateWorker: DEBUG before RefreshLiveSegments()
2023-02-08 18:02:15.155 T:22024   error <general>: AddOnLog: inputstream.adaptive: SegmentUpdateWorker: DEBUG after RefreshLiveSegments()
2023-02-08 18:02:16.155 T:22024   error <general>: AddOnLog: inputstream.adaptive: SegmentUpdateWorker: DEBUG before RefreshLiveSegments()
2023-02-08 18:02:16.161 T:22020   error <general>: AddOnLog: inputstream.adaptive: DEBUG after sleep()

Address sanitizer report:

==21945==ERROR: AddressSanitizer: heap-use-after-free on address 0x7f402596e960 at pc 0x7f40131c4944 bp 0x7f402616de50 sp 0x7f402616de40
READ of size 8 at 0x7f402596e960 thread T53
    #0 0x7f40131c4943 in adaptive::AdaptiveStream::start_stream() /home/dobo/kodi/inputstream.adaptive/src/common/AdaptiveStream.cpp:610
    xbmc#1 0x7f4013178317 in CInputStreamAdaptive::OpenStream(int) /home/dobo/kodi/inputstream.adaptive/src/main.cpp:309
    xbmc#2 0x7f4013187f07 in kodi::addon::CInstanceInputStream::ADDON_OpenStream(AddonInstance_InputStream const*, int) (/usr/lib/kodi/addons/inputstream.adaptive/inputstream.adaptive.so.20.3.2+0x387f07)
    xbmc#3 0x55abad48474b in CDVDDemuxClient::OpenStream(int) (/usr/lib/kodi/kodi.bin+0xb7c74b)
    xbmc#4 0x55abad508385 in CVideoPlayer::OpenStream(CCurrentStream&, long, int, int, bool) (/usr/lib/kodi/kodi.bin+0xc00385)
    xbmc#5 0x55abad508bba in CVideoPlayer::OpenDefaultStreams(bool) (/usr/lib/kodi/kodi.bin+0xc00bba)
    xbmc#6 0x55abad50a857 in CVideoPlayer::Prepare() (/usr/lib/kodi/kodi.bin+0xc02857)
    xbmc#7 0x55abad510d45 in CVideoPlayer::Process() (/usr/lib/kodi/kodi.bin+0xc08d45)
    xbmc#8 0x55abad758396 in CThread::Action() (/usr/lib/kodi/kodi.bin+0xe50396)
    xbmc#9 0x55abae0f0e24  (/usr/lib/kodi/kodi.bin+0x17e8e24)
    xbmc#10 0x55abad755dba  (/usr/lib/kodi/kodi.bin+0xe4ddba)
    xbmc#11 0x7f403d4d72c2 in execute_native_thread_routine /usr/src/debug/gcc/gcc/libstdc++-v3/src/c++11/thread.cc:82
    xbmc#12 0x7f403dd8cbb4  (/usr/lib/libc.so.6+0x85bb4)
    xbmc#13 0x7f403de0ed8f  (/usr/lib/libc.so.6+0x107d8f)

0x7f402596e960 is located 303456 bytes inside of 303840-byte region [0x7f4025924800,0x7f402596eae0)
freed by thread T57 here:
    #0 0x7f403fac178a in operator delete(void*, unsigned long) /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_new_delete.cpp:164
    xbmc#1 0x7f40131de17d in std::__new_allocator<adaptive::AdaptiveTree::Segment>::deallocate(adaptive::AdaptiveTree::Segment*, unsigned long) /usr/include/c++/12.2.1/bits/new_allocator.h:158
    xbmc#2 0x7f40131d974a in std::allocator_traits<std::allocator<adaptive::AdaptiveTree::Segment> >::deallocate(std::allocator<adaptive::AdaptiveTree::Segment>&, adaptive::AdaptiveTree::Segment*, unsigned long) /usr/include/c++/12.2.1/bits/alloc_traits.h:496
    xbmc#3 0x7f40131d33cb in std::_Vector_base<adaptive::AdaptiveTree::Segment, std::allocator<adaptive::AdaptiveTree::Segment> >::_M_deallocate(adaptive::AdaptiveTree::Segment*, unsigned long) /usr/include/c++/12.2.1/bits/stl_vector.h:387
    xbmc#4 0x7f40131edabd in std::_Vector_base<adaptive::AdaptiveTree::Segment, std::allocator<adaptive::AdaptiveTree::Segment> >::~_Vector_base() /usr/include/c++/12.2.1/bits/stl_vector.h:366
    xbmc#5 0x7f40131edb57 in std::vector<adaptive::AdaptiveTree::Segment, std::allocator<adaptive::AdaptiveTree::Segment> >::~vector() /usr/include/c++/12.2.1/bits/stl_vector.h:733
    xbmc#6 0x7f40131ea67f in adaptive::SPINCACHE<adaptive::AdaptiveTree::Segment>::~SPINCACHE() /home/dobo/kodi/inputstream.adaptive/src/common/AdaptiveTree.h:44
    xbmc#7 0x7f40131eae13 in adaptive::AdaptiveTree::Representation::~Representation() /home/dobo/kodi/inputstream.adaptive/src/common/AdaptiveTree.h:208
    xbmc#8 0x7f40131eb5c2 in adaptive::AdaptiveTree::AdaptationSet::~AdaptationSet() /home/dobo/kodi/inputstream.adaptive/src/parser/../common/AdaptiveTree.h:326
    xbmc#9 0x7f40131ecef6 in adaptive::AdaptiveTree::Period::~Period() /home/dobo/kodi/inputstream.adaptive/src/parser/../common/AdaptiveTree.h:462
    xbmc#10 0x7f40131e19ef in adaptive::AdaptiveTree::~AdaptiveTree() /home/dobo/kodi/inputstream.adaptive/src/common/AdaptiveTree.cpp:92
    xbmc#11 0x7f401323f6a4 in adaptive::DASHTree::~DASHTree() /home/dobo/kodi/inputstream.adaptive/src/parser/DASHTree.h:16
    xbmc#12 0x7f401323f6bf in adaptive::DASHTree::~DASHTree() /home/dobo/kodi/inputstream.adaptive/src/parser/DASHTree.h:16
    xbmc#13 0x7f401323f73c in std::default_delete<adaptive::DASHTree>::operator()(adaptive::DASHTree*) const /usr/include/c++/12.2.1/bits/unique_ptr.h:95
    xbmc#14 0x7f401323c926 in std::unique_ptr<adaptive::DASHTree, std::default_delete<adaptive::DASHTree> >::~unique_ptr() /usr/include/c++/12.2.1/bits/unique_ptr.h:396
    xbmc#15 0x7f4013237aa8 in adaptive::DASHTree::RefreshLiveSegments() /home/dobo/kodi/inputstream.adaptive/src/parser/DASHTree.cpp:1962
    xbmc#16 0x7f40131e7842 in adaptive::AdaptiveTree::SegmentUpdateWorker() /home/dobo/kodi/inputstream.adaptive/src/common/AdaptiveTree.cpp:431
    xbmc#17 0x7f4013208eea in void std::__invoke_impl<void, void (adaptive::AdaptiveTree::*)(), adaptive::AdaptiveTree*>(std::__invoke_memfun_deref, void (adaptive::AdaptiveTree::*&&)(), adaptive::AdaptiveTree*&&) /usr/include/c++/12.2.1/bits/invoke.h:74
    xbmc#18 0x7f4013208d56 in std::__invoke_result<void (adaptive::AdaptiveTree::*)(), adaptive::AdaptiveTree*>::type std::__invoke<void (adaptive::AdaptiveTree::*)(), adaptive::AdaptiveTree*>(void (adaptive::AdaptiveTree::*&&)(), adaptive::AdaptiveTree*&&) /usr/include/c++/12.2.1/bits/invoke.h:96
    xbmc#19 0x7f4013208cc6 in void std::thread::_Invoker<std::tuple<void (adaptive::AdaptiveTree::*)(), adaptive::AdaptiveTree*> >::_M_invoke<0ul, 1ul>(std::_Index_tuple<0ul, 1ul>) /usr/include/c++/12.2.1/bits/std_thread.h:258
    xbmc#20 0x7f4013208c7f in std::thread::_Invoker<std::tuple<void (adaptive::AdaptiveTree::*)(), adaptive::AdaptiveTree*> >::operator()() /usr/include/c++/12.2.1/bits/std_thread.h:265
    xbmc#21 0x7f4013208c63 in std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (adaptive::AdaptiveTree::*)(), adaptive::AdaptiveTree*> > >::_M_run() /usr/include/c++/12.2.1/bits/std_thread.h:210
    xbmc#22 0x7f403d4d72c2 in execute_native_thread_routine /usr/src/debug/gcc/gcc/libstdc++-v3/src/c++11/thread.cc:82

previously allocated by thread T53 here:
    #0 0x7f403fac0672 in operator new(unsigned long) /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_new_delete.cpp:95
    xbmc#1 0x7f40131deab1 in std::__new_allocator<adaptive::AdaptiveTree::Segment>::allocate(unsigned long, void const*) /usr/include/c++/12.2.1/bits/new_allocator.h:137
    xbmc#2 0x7f40131db727 in std::allocator_traits<std::allocator<adaptive::AdaptiveTree::Segment> >::allocate(std::allocator<adaptive::AdaptiveTree::Segment>&, unsigned long) /usr/include/c++/12.2.1/bits/alloc_traits.h:464
    xbmc#3 0x7f40131d5b81 in std::_Vector_base<adaptive::AdaptiveTree::Segment, std::allocator<adaptive::AdaptiveTree::Segment> >::_M_allocate(unsigned long) /usr/include/c++/12.2.1/bits/stl_vector.h:378
    xbmc#4 0x7f40131d1308 in std::vector<adaptive::AdaptiveTree::Segment, std::allocator<adaptive::AdaptiveTree::Segment> >::reserve(unsigned long) /usr/include/c++/12.2.1/bits/vector.tcc:79
    xbmc#5 0x7f401322dd61 in end /home/dobo/kodi/inputstream.adaptive/src/parser/DASHTree.cpp:1253
    xbmc#6 0x7f403c4d8263  (/usr/lib/libexpat.so.1+0xd263)

Thread T53 created by T0 here:
    #0 0x7f403fa64207 in __interceptor_pthread_create /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_interceptors.cpp:207
    xbmc#1 0x7f403d4d73a9 in __gthread_create /usr/src/debug/gcc/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/x86_64-pc-linux-gnu/bits/gthr-default.h:663
    xbmc#2 0x7f403d4d73a9 in std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) /usr/src/debug/gcc/gcc/libstdc++-v3/src/c++11/thread.cc:147

Thread T57 created by T53 here:
    #0 0x7f403fa64207 in __interceptor_pthread_create /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_interceptors.cpp:207
    xbmc#1 0x7f403d4d73a9 in __gthread_create /usr/src/debug/gcc/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/x86_64-pc-linux-gnu/bits/gthr-default.h:663
    xbmc#2 0x7f403d4d73a9 in std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) /usr/src/debug/gcc/gcc/libstdc++-v3/src/c++11/thread.cc:147
    xbmc#3 0x7f40131e751e in adaptive::AdaptiveTree::StartUpdateThread() /home/dobo/kodi/inputstream.adaptive/src/common/AdaptiveTree.cpp:418
    xbmc#4 0x7f401323398d in adaptive::DASHTree::open(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >) /home/dobo/kodi/inputstream.adaptive/src/parser/DASHTree.cpp:1639
    xbmc#5 0x7f401328c8ed in SESSION::CSession::Initialize() /home/dobo/kodi/inputstream.adaptive/src/Session.cpp:248
    xbmc#6 0x7f4013175f30 in CInputStreamAdaptive::Open(kodi::addon::InputstreamProperty const&) /home/dobo/kodi/inputstream.adaptive/src/main.cpp:86
    xbmc#7 0x7f40131871d5 in kodi::addon::CInstanceInputStream::ADDON_Open(AddonInstance_InputStream const*, INPUTSTREAM_PROPERTY*) (/usr/lib/kodi/addons/inputstream.adaptive/inputstream.adaptive.so.20.3.2+0x3871d5)
    xbmc#8 0x55abad46eddc in CInputStreamAddon::Open() (/usr/lib/kodi/kodi.bin+0xb66ddc)

SUMMARY: AddressSanitizer: heap-use-after-free /home/dobo/kodi/inputstream.adaptive/src/common/AdaptiveStream.cpp:610 in adaptive::AdaptiveStream::start_stream()
Shadow bytes around the buggy address:
  0x0fe884b25cd0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0fe884b25ce0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0fe884b25cf0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0fe884b25d00: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0fe884b25d10: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
=>0x0fe884b25d20: fd fd fd fd fd fd fd fd fd fd fd fd[fd]fd fd fd
  0x0fe884b25d30: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0fe884b25d40: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0fe884b25d50: fd fd fd fd fd fd fd fd fd fd fd fd fa fa fa fa
  0x0fe884b25d60: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0fe884b25d70: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==21945==ABORTING
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants