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

Rework the listening IP/interface selection code #11592

Merged

Conversation

sledgehammer999
Copy link
Member

@sledgehammer999 sledgehammer999 commented Dec 6, 2019

Closes #11561

It started as a simple fix for #11561. But as I dug deeper I fixed more and more things. And it became a full blown refactor.

With this PR:

  1. As per 1.2.x docs, the default setting (aka all interfaces + all addresses) is to also explicitly set the IPv6_ANY address
  2. Now if a user chooses "all addresses" from a specific interface, we tell libtorrent to bind to that specific interface instead of listing to it all the addresses of the interface. This has the benefit that libtorrent will automatically follow any changes to that interface. This is of benefit to VPN users when their connection drops and then they get assigned a new "local" ip.
  3. Two new options in the drop down menu for addresses. All IPv4 Addresses and All IPv6 Addresses.
  4. Due to the above, the option "Listen to IPv6 address" is removed. This warrants a WebAPI major version bump (not done in this PR).
  5. I discovered a Qt bug concerning the textual representation of IPv6 and scope id. Read the code comments for details. This bug essentially resulted in libtorrent not binding on the set IPv6 address but instead to 0.0.0.0.

PS: I am not very good with choosing variable/function names.

@sledgehammer999 sledgehammer999 added the Network Issues related to network connectivity label Dec 6, 2019
@sledgehammer999 sledgehammer999 added this to the 4.2.1 milestone Dec 6, 2019
Copy link
Member

@Chocobo1 Chocobo1 left a comment

Choose a reason for hiding this comment

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

Some quick reviews.. no need to wait for my review completion if you want to force push/update.

src/gui/advancedsettings.cpp Outdated Show resolved Hide resolved
src/webui/api/appcontroller.cpp Outdated Show resolved Hide resolved
src/webui/api/appcontroller.cpp Outdated Show resolved Hide resolved
src/gui/advancedsettings.cpp Outdated Show resolved Hide resolved
src/gui/advancedsettings.cpp Outdated Show resolved Hide resolved
src/base/bittorrent/session.cpp Outdated Show resolved Hide resolved
src/base/bittorrent/session.cpp Outdated Show resolved Hide resolved
src/base/bittorrent/session.cpp Outdated Show resolved Hide resolved
src/base/bittorrent/session.cpp Outdated Show resolved Hide resolved
src/base/bittorrent/session.cpp Outdated Show resolved Hide resolved
src/base/bittorrent/session.cpp Outdated Show resolved Hide resolved
@sledgehammer999
Copy link
Member Author

Guys, I think I addressed all your comments so far. Take a look at the new commit.

src/webui/api/appcontroller.cpp Outdated Show resolved Hide resolved
src/gui/advancedsettings.cpp Outdated Show resolved Hide resolved
src/gui/advancedsettings.cpp Outdated Show resolved Hide resolved
src/base/utils/net.cpp Outdated Show resolved Hide resolved
src/base/bittorrent/session.h Outdated Show resolved Hide resolved
src/base/bittorrent/session.cpp Outdated Show resolved Hide resolved
src/base/bittorrent/session.cpp Outdated Show resolved Hide resolved
src/base/bittorrent/session.cpp Outdated Show resolved Hide resolved
src/base/bittorrent/session.cpp Outdated Show resolved Hide resolved
src/base/bittorrent/session.cpp Outdated Show resolved Hide resolved
@SadPencil

This comment has been minimized.

src/base/bittorrent/session.cpp Outdated Show resolved Hide resolved
// as scope id. Furthermore, QHostAddress doesn't have any convenient method to
// affect this, so we jump through hoops here.
if (addr.protocol() != QAbstractSocket::IPv6Protocol)
return addr;
Copy link
Member

Choose a reason for hiding this comment

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

canonicalIPv6Addr shouldn't return non-IPv6 address!

Copy link
Member Author

Choose a reason for hiding this comment

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

So return a null QHostAddress?

@sledgehammer999
Copy link
Member Author

In this push, I addressed almost all the comments, apart 2 from glassez.

src/gui/advancedsettings.cpp Outdated Show resolved Hide resolved
src/base/bittorrent/session.cpp Outdated Show resolved Hide resolved
Chocobo1
Chocobo1 previously approved these changes Dec 9, 2019
Copy link
Member

@Chocobo1 Chocobo1 left a comment

Choose a reason for hiding this comment

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

No more comments from me.

Also I noticed this patch: arvidn/libtorrent#4166
If that patch could simplify our work here, it might be worth to add some #if conditionals to the relevant code.

// as scope id. Furthermore, QHostAddress doesn't have any convenient method to
// affect this, so we jump through hoops here.
if (addr.protocol() != QAbstractSocket::IPv6Protocol)
return {};
Copy link
Member

Choose a reason for hiding this comment

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

If applying this function to IPv4 address isn't valid "use case" you should prevent it in any way (at least add an appropriate assertion). Otherwise it may allow logically incorrect code.

Copy link
Member Author

Choose a reason for hiding this comment

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

I am confused. How do I prevent it in any way?
And won't the assertion work only in debug?

Copy link
Member

Choose a reason for hiding this comment

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

How do I prevent it in any way?

You can throw RuntimeError...

Or you can modify it to be valid for any IP (and rename it to canonicalIPAddr).

Copy link
Member

Choose a reason for hiding this comment

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

Or even it can return IPv6 representstion of IPv4... unless I am wrong it is possible.

Copy link
Member Author

Choose a reason for hiding this comment

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

QHostAddress::toIPv6Address() seems to do the job. So it becomes:

if (addr.protocol() != QAbstractSocket::IPv6Protocol)
                return {addr.toIPv6Address()};

Copy link
Member

Choose a reason for hiding this comment

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

And also apply all remaining modifications.

Copy link
Member

Choose a reason for hiding this comment

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

Or it already in "canonical" form?

Copy link
Member Author

Choose a reason for hiding this comment

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

Or it already in "canonical" form?

It can't be, because at this point it is IPv4.
If you mean below, there is no way to know beforehand. So we convert unconditionally.

Copy link
Member

@glassez glassez Dec 9, 2019

Choose a reason for hiding this comment

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

I would implement another variant instead. I mean canonicalIPAddr that returns IP of the same type as its argument.
BTW, we can use it unconditionally since it always returns valid result.

src/base/bittorrent/session.cpp Outdated Show resolved Hide resolved
@sledgehammer999
Copy link
Member Author

I think I addressed everything and I did some furhter refactor. Due to that I implemented it as a separate temporary commit. It will be easier for you to see what I changed.

@sledgehammer999
Copy link
Member Author

The missing part is the webui code itself. @Chocobo1 will you be able to plug in the correct js/html changes?

src/base/bittorrent/session.cpp Outdated Show resolved Hide resolved
src/base/utils/net.cpp Show resolved Hide resolved
src/gui/advancedsettings.cpp Outdated Show resolved Hide resolved
src/webui/api/appcontroller.cpp Outdated Show resolved Hide resolved
src/webui/api/appcontroller.cpp Outdated Show resolved Hide resolved
@Chocobo1
Copy link
Member

Chocobo1 commented Dec 9, 2019

@Chocobo1 will you be able to plug in the correct js/html changes?

Currently I'm low on free time to write code unfortunately.

@glassez
Copy link
Member

glassez commented Dec 10, 2019

An empty string for all address is fine for me or even better IMO: 0.0.0.0,::

Isn't empty string treated as "any IP" by app core? Then it should be used here as well.

@sledgehammer999
Copy link
Member Author

Now the webui receives an empty string to mean all addresses, 0.0.0.0 to mean All IPv4 addresses and :: to mean All IPv6 addresses. This seems to have the benefit of the least possible code/refactoring.

I also changed how the GUI populates the comboboxes to match the logic of the WebUI comboboxes.

And I probably changed other things here and there. So forgive me but please take another look at the whole thing.

Copy link
Member

@Chocobo1 Chocobo1 left a comment

Choose a reason for hiding this comment

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

only some minor things left, overall it's looking good.

src/gui/advancedsettings.cpp Outdated Show resolved Hide resolved
src/gui/advancedsettings.cpp Show resolved Hide resolved
src/gui/advancedsettings.cpp Outdated Show resolved Hide resolved
@sledgehammer999
Copy link
Member Author

On another note, I just noticed that we do a lot of

// ifaceAddr is of type QHostAddres
functionThatTakesQString(ifaceAddr.isNull() ? QString {} : ifaceAddr.toString());

But I realize that we can collapse it to:

functionThatTakesQString(ifaceAddr.toString());

I'll make the changes later (only code affected by me).

@sledgehammer999
Copy link
Member Author

Closes #11632

@sledgehammer999
Copy link
Member Author

@glassez do you approve?

@glassez
Copy link
Member

glassez commented Dec 12, 2019

I would still change canonicalIPv6Addr to suggested canonicalIPAddr form. But you can ignore this opinion.

@sledgehammer999
Copy link
Member Author

I would still change canonicalIPv6Addr to suggested canonicalIPAddr form.

IMO, I don't want to give the impression that the function can be used with IPv4. (Yes, it will work but it shouldn't be used for IPv4).

@glassez
Copy link
Member

glassez commented Dec 12, 2019

it shouldn't be used for IPv4

You cannot forbid it since function accepts generic host address (function name isn't enough, there can be use case when parameter is bypassed unchecked). You either can break it at runtime (throw an exception) or change it to be valid (have a meaning) for any kind of host address.
If my argument is irrelevant to you, you can merge this PR, I have nothing to add.

@sledgehammer999
Copy link
Member Author

No, I meant that it is discouraged through the function name.

Thank you all for the reviewing.

@sledgehammer999 sledgehammer999 merged commit d09c5e5 into qbittorrent:master Dec 12, 2019
@sledgehammer999 sledgehammer999 deleted the refactor_listeningAddr branch December 12, 2019 18:24
@ghost
Copy link

ghost commented Dec 21, 2019

This introduced the tracker not working bug in v 4.2.1
The annnounce goes through and tracker status says "working" but still the torrent gets moved to error section unless you expilcity set "Optional IP address to bind to" to "All IPv4 Addresses"
#11691
@sledgehammer999 @glassez @Chocobo1

@FranciscoPombal
Copy link
Member

@sledgehammer999 @glassez @Chocobo1
There is new information available about this topic in the libtorrent documentation:
arvidn/libtorrent#4267

Not sure if this warrants any changes/additions to the code introduced in this PR, but I thought I should give the heads-up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Network Issues related to network connectivity
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4.2.0 not sending IPv6 parameter to announce
5 participants