microsoft / MixedRealityToolkit-Unity

This repository is for the legacy Mixed Reality Toolkit (MRTK) v2. For the latest version of the MRTK please visit https://github.com/MixedRealityToolkit/MixedRealityToolkit-Unity
https://aka.ms/mrtkdocs
MIT License
5.99k stars 2.12k forks source link

SessionManager.UI Throws Error code 5 on port 20605 #206

Closed StephenHodgson closed 7 years ago

StephenHodgson commented 7 years ago

SessionManager.UI Throws Error code 5 on port 20605.

Tested this on 3 different machines w/firewalls turned off.

NeerajW commented 7 years ago

I believe the sharing code uses a range of port numbers 20346-20602. Try changing your port number to be within this range.

StephenHodgson commented 7 years ago

Shouldn't this just work right out of the box? This is a clean install of the HoloToolkit from Git.

Repo steps: Download HoloToolKit from Git Create new project in Unity Import HoloToolKit Start Sharing Service via Unity Editor: HoloToolKit/Launch Sharing Service Start Session Manager via Unity Editor: HoloToolKit/Launch Session Manager

Status box of Session Manager shows:

00001: SharingService [....\Source\Common\Private\XSocketManagerImpl.cpp (688)]: Failed to create incoming connection on port 20605. Error code: 5

00002: SharingService: connected to Session List Server

00003: SESSION Default ADDED

Also, I'm not sure where I should be changing the port number. Shouldn't this be updated in the repo?

NeerajW commented 7 years ago

@alexdrenea any ideas?

alexdrenea commented 7 years ago

This is normal / expected. Port 20605 is used for the auto-discovery mechanism. Every component of the HoloToolkit sharing platform (client, server, session manager) will try to open a socket on port 20605 to listen for discovery requests by others. The port is "hardcoded" and is required to be a fixed port so that it can be easy to send a broadcast on the network. When you run 2 or more components on the same machine (in your case, server and manager) both will try to open that connection on 20605 and obviously the second one will fail since the port is already in use.

This is normally not a problem for 2 reasons. Even if the port opening fails, that does not affect the sharing functionality since this is an extra feature and not critical to the system. Even then, in most cases, you only need to find the server via auto-discovery and not other components so as long as you open the server first others will be able to find it and there won't be any issues.

I've mentioned this in a post on the HoloLens forums as well - https://forums.hololens.com/discussion/comment/7653#Comment_7653

I am thinking maybe we could update the readme to make it a bit clearer? @NeerajW do you want me to try and come up with an initial draft ?

StephenHodgson commented 7 years ago

Okay, that makes a lot more sense. I remember reading your comment on the forum, but didn't quite understand until you explained it here.

In either case, I don't think throwing an error code should be "normal / expected". Should we be handling this better?

alexdrenea commented 7 years ago

Not sure about handling it better. After all it is a legit error - the application cannot open a connection. just that in our case, we ourselves via another application from the same platform are blocking it for a legit reason. There might be cases where some other random process is blocking the port and then you need to know about that.

I think the best we could do is (if possible) change the error message to be more descriptive and potentially update the documentation.

StephenHodgson commented 7 years ago

Maybe there's a way to know if another application has already initiated the auto discovery on that port, and prevent the attempt to connect?

Every component of the HoloToolkit sharing platform (client, server, session manager) will try to open a socket on port 20605 to listen for discovery requests by others.

If this is true, then we should be able to know if an app is already using it if we send a request to connect before we open a socket on that port.

This way we don't have to change the behavior of the thrown error, and keep that functionality to legitimate errors, and prevent the error from being thrown in cases where we already have an application on the port.

I'd look through the source myself, but frustratingly, my company policy does not allow me to sign the CLA.

NeerajW commented 7 years ago

@alexdrenea it seems worth looking into @HodgsonSDAS's suggestion. What do you think?

alexdrenea commented 7 years ago

Ah, I replied that day but my connection was unstable and apparently it didn't actually submit.

and keep that functionality to legitimate errors, and prevent the error from being thrown in cases where we already have an application on the port.

Like I said, the error is a legitimate error, and is only thrown if an application is blocking the port, regardless if that application is from the toolkit (client, manager, server) or not.

If this is true, then we should be able to know if an app is already using it if we send a request to connect before we open a socket on that port.

That is true, but there's no easy way of knowing if the other app is part of the toolkit or not. Any app can block the port and we must ensure we let the user know that there's an issue.

StephenHodgson commented 7 years ago

That is true, but there's no easy way of knowing if the other app is part of the toolkit or not.

@alexdrenea Would this be much different than the AutoDiscovery in the SharingStage.cs update you did?

For Example: If we've auto discovered a server and connected to it, don't try to connect to port 20605 else connect

alexdrenea commented 7 years ago

:) that's exactly what I was thinking when I said it's not easy . Essentially, when you open the SessionManager or the Client, you can run an AutoDiscovery to see if there's a reply with your own IP. In which case, you don't attempt to open that port yourself.

However, I am still not satisfied that this is a good solution. First of all, it will cause the component to start slower (or at least, its AutoDiscovery service will start slower since it has to wait for responses before it attempts to open the port). Second, for the server component in particular, I think this is a bad idea, since it's crucial for the server to have the feature enabled and the user should know if it's not working no matter who's blocking the port. Finally, let's look at the actual problem that we are trying to solve here? From my point of view it's a simple, expected error that in most cases won't even reproduce, and when it does it doesn't affect any functionality.

If there was a simple fix, I would be all for it but I don't think the current solution is overly complicated for what benefit it brings.

jwittner commented 7 years ago

Can we catch the exception and improve the error message?

alexdrenea commented 7 years ago

Starting from the error itself ...

SharingService [...\holotoolkit\sharing\src\source\common\private\xsocketmanagerimpl.cpp (668)]: Failed to create incoming connection on port 20605. Error code: 5

I found the code that generates the message:

    // Startup the peer interface with the given socket settings.  Will fail if we already have a peer interface for this host
    RakNet::StartupResult startupResult = RakNet::STARTUP_OTHER_FAILURE;

    try
    {
        startupResult = peerConnection->m_peer->Startup(discoveryCommand->GetMaxConnections(), &socketDescriptor, 1);
    }
    catch (...) {}

    if (startupResult != RakNet::RAKNET_STARTED)
    {
        LogError("Failed to create incoming connection on port %u.  Error code: %u", discoveryCommand->GetPort(), startupResult);
        return;
    }

By the looks of it it's actually handling the case quite nicely and based on the comment itself it seems that whoever wrote it was thinking exactly in the lines of our conversation here.

The code itself seems to be shared by both the server and the manager and it's not straight up clear how it gets called (or at least I can't figure it out without digging deeper). So at this point I personaly, will stay way from changing anything other than the string message because I don't know what and in how will the changes affect the overall system.

If anyone wants to take a stab at whatever other change, I can help with an extra eye (ok, 2 extra eyes) in the review phase.

P.S. anyone know if it's possible to reference the file and code itself from the repo rather than copy paste? - same how you do in the code review?

jwittner commented 7 years ago

anyone know if it's possible to reference the file and code itself from the repo rather than copy paste? - same how you do in the code review?

Far as I can tell you can get links by selecting from the code on the left (yellow highlight a section), then your URL will update like this: https://github.com/Microsoft/HoloToolkit/blob/master/Sharing/Src/Source/Common/Private/XSocketManagerImpl.cpp#L666-L670

Doesn't embed the text though. =(

StephenHodgson commented 7 years ago

Hmm, well considering I'm still having issues just getting the HoloToolkit solution to even build on my machine, so I will not be too much help testing and editing. (But I did manage to get clearance to sign the CLA!)

I did a quick test and started the Session List Manager UI before the Sharing Service Server. I noticed that the Session Manager UI will automatically connect to the Sharing Service and create a default session.

Why do we need/want the Session List Manager UI to create a auto discovery connection on that port when it starts up, if we assume people will always start the Sharing Services first? Shouldn't this ideally only be handled by the Server anyway?

Is there a way to get the Session List Manager UI to attempt to connect to the sharing service server before we try to process the discover response command? And if we successfully get the session server, not attempt the connection to the auto discovery port?

StephenHodgson commented 7 years ago

I'm going to close this issue and open it in the main HoloToolKit

dtmnash commented 6 years ago

I just ran into this same issue. What i don't understand, if two apps from the same machine can't join the same session, is how the Session Manager UI app is able to join from the same machine without a problem.

In our case we are building a Unity2D app and a Unity3D app (HoloLens) that needs to send messages back and forth. The 2D app is just responsible for controlling the experience of the HoloLens app. Switch scenes, enable/disable GOs, etc.

Running them together on the same machine in development produces the error above.