Skip to content

Bugfixes for aria2 and convert_magnet#1608

Merged
gazpachoking merged 7 commits intoFlexget:developfrom
drwyrm:for-upstream
Jan 5, 2017
Merged

Bugfixes for aria2 and convert_magnet#1608
gazpachoking merged 7 commits intoFlexget:developfrom
drwyrm:for-upstream

Conversation

@drwyrm
Copy link
Copy Markdown
Contributor

@drwyrm drwyrm commented Jan 5, 2017

Fixes #1514 and #1604

drwyrm added 3 commits January 5, 2017 01:28
Prevent crash in case both download and aria2 output plugins are enabled at the same time.

Download plugin may move the temp .torrent file created by convert_magnet away, causing aria2 plugin to crash.

Fixes Flexget#1604
# for some reason the info_hash needs to be bytes but it's a struct called sha1_hash
params['info_hash'] = bytes(params['info_hash'])
lt_version = [int(v) for v in libtorrent.version.split('.')]
if lt_version[0] > 0 or (lt_version[0] == 0 and lt_version[1] == 16 and lt_version[2] > 13):
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this be more clearly expressed as if lt_version > [0, 16, 13]:? Also, are you sure this is to do with a change since libtorrent 0.16.14, and not something to do with python 2 vs 3? Have, (or can you,) test with both python 2 and 3?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$ python2.7
Python 2.7.12 (default, Nov 19 2016, 06:48:10) 
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> magnet_uri='magnet:?xt=urn:btih:2fd26e37489b543179faefee0febf199b8f35698&dn=Indiana+Jones+and+the+Raiders+of+the+Lost+Ark+%281981%29+720p+BrRip+&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Fzer0day.ch%3A1337&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Fpublic.popcorn-tracker.org%3A6969'
>>> import libtorrent
>>> libtorrent.version
'1.0.7.0'
>>> params = libtorrent.parse_magnet_uri(magnet_uri)
>>> session = libtorrent.session()
>>> params['info_hash'] = bytes(params['info_hash'])
>>> handle = libtorrent.add_magnet_uri(session, magnet_uri, params)
>>> 

$ python3.5
Python 3.5.2 (default, Nov 17 2016, 17:05:23) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> magnet_uri='magnet:?xt=urn:btih:2fd26e37489b543179faefee0febf199b8f35698&dn=Indiana+Jones+and+the+Raiders+of+the+Lost+Ark+%281981%29+720p+BrRip+&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Fzer0day.ch%3A1337&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Fpublic.popcorn-tracker.org%3A6969'
>>> import libtorrent
>>> libtorrent.version
'1.0.7.0'
>>> params = libtorrent.parse_magnet_uri(magnet_uri)
>>> session = libtorrent.session()
>>> params['info_hash'] = bytes(params['info_hash'])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'sha1_hash' object is not iterable

$ python2.7
Python 2.7.6 (default, Oct 26 2016, 20:46:32) 
[GCC 4.8.4] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> magnet_uri='magnet:?xt=urn:btih:2fd26e37489b543179faefee0febf199b8f35698&dn=Indiana+Jones+and+the+Raiders+of+the+Lost+Ark+%281981%29+720p+BrRip+&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Fzer0day.ch%3A1337&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Fpublic.popcorn-tracker.org%3A6969'
>>> import libtorrent
>>> libtorrent.version
'0.16.13.0'
>>> params = libtorrent.parse_magnet_uri(magnet_uri)
>>> session = libtorrent.session()
>>> params['info_hash'] = bytes(params['info_hash'])
>>> handle = libtorrent.add_magnet_uri(session, magnet_uri, params)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: No registered converter was able to produce a C++ rvalue of type libtorrent::big_number from this Python object of type str

I don't have python3 on the machine that has libtorrent 0.16.13, so, I can't test it, sorry.

Seems that it is still broken (both before and after this patch) for python 3, for a different reason though.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is the test on python3.5 without the bytes cast:

$ python3.5
Python 3.5.2 (default, Nov 17 2016, 17:05:23) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> magnet_uri='magnet:?xt=urn:btih:2fd26e37489b543179faefee0febf199b8f35698&dn=Indiana+Jones+and+the+Raiders+of+the+Lost+Ark+%281981%29+720p+BrRip+&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Fzer0day.ch%3A1337&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Fpublic.popcorn-tracker.org%3A6969'
>>> import libtorrent
>>> libtorrent.version
'1.0.7.0'
>>> params = libtorrent.parse_magnet_uri(magnet_uri)
>>> session = libtorrent.session()
>>> handle = libtorrent.add_magnet_uri(session, magnet_uri, params)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: No registered converter was able to produce a C++ rvalue of type bytes from this Python object of type sha1_hash

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, how bout we switch it like in the other issue you mentioned lt.big_number(params['info_hash']) instead of bytes(), does that work?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like this?

$ python3.5
Python 3.5.2 (default, Nov 17 2016, 17:05:23) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> magnet_uri='magnet:?xt=urn:btih:2fd26e37489b543179faefee0febf199b8f35698&dn=Indiana+Jones+and+the+Raiders+of+the+Lost+Ark+%281981%29+720p+BrRip+&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969&tr=udp%3A%2F%2Fzer0day.ch%3A1337&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969&tr=udp%3A%2F%2Fpublic.popcorn-tracker.org%3A6969'
>>> import libtorrent
>>> libtorrent.version
'1.0.7.0'
>>> params = libtorrent.parse_magnet_uri(magnet_uri)
>>> session = libtorrent.session()
>>> params['info_hash'] = libtorrent.big_number(params['info_hash'])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
Boost.Python.ArgumentError: Python argument types in
    sha1_hash.__init__(sha1_hash, sha1_hash)
did not match C++ signature:
    __init__(_object*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)
    __init__(_object*)

@gazpachoking
Copy link
Copy Markdown
Member

gazpachoking commented Jan 5, 2017

Shoot. Maybe lt.bignumber(bytes()) on python 3? (I'm just grasping at straws now...)
It's working properly on python 2 with both versions of libtorrent after the patch already?

@drwyrm
Copy link
Copy Markdown
Contributor Author

drwyrm commented Jan 5, 2017

Yes, it is working properly for both 0.16.13 and 1.0.7 when using python2.7 after the patch.

Can't cast params['info_hash'] to bytes():
TypeError: 'sha1_hash' object is not iterable

But I think I found the fix for python3:

>>> params = libtorrent.parse_magnet_uri(magnet_uri)
>>> params['info_hash'] = params['info_hash'].to_bytes()
>>> handle = libtorrent.add_magnet_uri(session, magnet_uri, params)

@drwyrm
Copy link
Copy Markdown
Contributor Author

drwyrm commented Jan 5, 2017

There is still one detail that needs fixing, unrelated to the previous fixes...

Options from the config file aren't being passed to aria2 when using this code path... Fix in a minute..

@cvium
Copy link
Copy Markdown
Contributor

cvium commented Jan 5, 2017

I'm not too happy about having multiple unrelated plugin changes in the same PR.

lt_version = [int(v) for v in libtorrent.version.split('.')]
if lt_version > [0,16,13,0]:
# for some reason the info_hash needs to be bytes but it's a struct called sha1_hash
params['info_hash'] = params['info_hash'].to_bytes()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From what I understand, the info_hash value still has to be set for older versions of libtorrent. It just expects a different type.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cvium It's already in the return value of params, it's just that certain versions of libtorrent can't handle feeding its own data structure back in as 'info_hash', so this just does the cast. At least that's my understanding.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, you're probably right. Hadn't read it properly it seems.

Copy link
Copy Markdown
Contributor Author

@drwyrm drwyrm Jan 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is correct. Problem is that the C++ bindings don't support custom data structures, so, it has to be converted to some standard. LT <= 0.16.13 simply used a string to represent the info_hash, and later versions use a custom struct.

Why libtorrent doesn't handle it by itself in the python-libtorrent glue? I have no idea, they should, IMO. Code above is ugly, and this caused breakage on pretty much every project that uses libtorrent.

@gazpachoking
Copy link
Copy Markdown
Member

I'm not too happy about having multiple unrelated plugin changes in the same PR.

Yeah, separate PRs for separate problems would have been nice. Especially since we can easily squash PRs at the end. Don't want to squash these 2 fixes into one commit though.

@drwyrm
Copy link
Copy Markdown
Contributor Author

drwyrm commented Jan 5, 2017

It's actually 4 bugfixes, for things I only found after starting the first 2...

  1. Compatibility for libtorrent <= 0.16.13
  2. Prevent crash on aria2 if convert_magnet fails or if it is used together with the download output plugin.
  3. Prevent crash on convert_magnet if using python3
  4. Pass aria2 options (including download path) in case we have a .torrent file instead of a URI.

My original intention was to have a separate/single commit/pr for 1 and 2, in a way that it could be easily cherry-picked individually, but I only found 3 and 4 later, after sending out the PR and after gazpachoking's review.

Unless there is a reason to not accept one of the fixes and accept the others, I don't see a point in having these as separate PRs, IMO, it's better to not squash anything and keep the full commit history. And even in this case, git allows you to cherrypick any of the individual commits if you don't want all 4 fixes.

I can still reshuffle things here and send another N PRs if you guys really want it, but there is no benefit from doing it at the end, bissection would be just the same if you just do a normal merge and keep commit history.

@gazpachoking gazpachoking merged commit 165d4a2 into Flexget:develop Jan 5, 2017
@gazpachoking
Copy link
Copy Markdown
Member

Having one commit for logical things, (whether that be from squashing separate prs, or just having clean commits,) is nice though when looking through the history, (or blame for a file,) rather than a bunch of jumbled stuff that normally ends up in there like 'typo', 'clean up docs' 'tweak whatever', 'oops', which are out of context and don't provide meaningful info. When just a small amount of code is getting touched I don't think the separation of commits adds quite as much value. For more complicated changes squashing doesn't seem as appropriate. That said, I'm not super fussed either way.

Unless there is a reason to not accept one of the fixes and accept the others, I don't see a point in having these as separate PRs, IMO, it's better to not squash anything and keep the full commit history. And even in this case, git allows you to cherrypick any of the individual commits if you don't want all 4 fixes.

Doesn't matter here I don't think. Just meant as a guideline in the future. Makes it easier to get stuff in right away instead of tying it up with other changes. I can assure you, having to manually cherry pick a commit rather than push the merge button on github could substantially delay a PR (in more places than just here.)

I'm not trying to lecture or scold btw, sorry if I'm coming across that way. Thanks for the contribution, and all your debugging work to get things working properly! 🍰

@drwyrm
Copy link
Copy Markdown
Contributor Author

drwyrm commented Jan 5, 2017 via email

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 this pull request may close these issues.

3 participants