Skip to content

Commit

Permalink
Adding mDNS logic to manually resolve .local hostnames. This is added…
Browse files Browse the repository at this point in the history
… for a few reasons, but mostly to make the system more robust.
  • Loading branch information
QuinnDamerell committed Dec 29, 2022
1 parent 7c2422c commit 378195d
Show file tree
Hide file tree
Showing 9 changed files with 449 additions and 14 deletions.
1 change: 1 addition & 0 deletions .github/workflows/pylint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ jobs:
pip install octoflatbuffers
pip install pillow
pip install certifi
pip install dnspython
pip install rsa
pip install sentry-sdk
pip install octoprint
Expand Down
4 changes: 4 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"deps",
"DGRAM",
"didnt",
"dnspython",
"filamentchange",
"firewalled",
"firstlayerdone",
Expand All @@ -37,6 +38,7 @@
"levelname",
"localauth",
"localip",
"mdns",
"mjpeg",
"mjpegstreamer",
"Mjpg",
Expand Down Expand Up @@ -74,6 +76,8 @@
"Pursa",
"Pylint",
"pythoncompat",
"rdataclass",
"rdclass",
"referer",
"repeattimer",
"requestsutils",
Expand Down
2 changes: 1 addition & 1 deletion devnotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@


## Install Other Branches:
- https://github.com/QuinnDamerell/OctoPrint-OctoEverywhere/archive/pip.zip
- https://github.com/QuinnDamerell/OctoPrint-OctoEverywhere/archive/mdns.zip

## Before checking in:
- Run in py2 env
Expand Down
45 changes: 37 additions & 8 deletions octoprint_octoeverywhere/WebStream/octowebstreamwshelper.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from octoprint_octoeverywhere.sentry import Sentry

from ..octohttprequest import OctoHttpRequest
from ..mdns import MDns
from ..octostreammsgbuilder import OctoStreamMsgBuilder
from ..localip import LocalIpHelper
from ..websocketimpl import Client
Expand Down Expand Up @@ -38,6 +39,7 @@ def __init__(self, streamId, logger, webStream, webStreamOpenMsg, openedTime):
self.OpenedTime = openedTime
self.Ws = None
self.FirstWsMessageSentToLocal = False
self.ResolvedLocalHostnameUrl = None

# These vars indicate if the actual websocket is opened or closed.
# This is different from IsClosed, which is tracking if the webstream closed status.
Expand Down Expand Up @@ -128,14 +130,41 @@ def AttemptConnection(self):
self.Logger.info(self.getLogMsgPrefix()+" failed to connect to relative path and has nothing else to try.")
return False
elif pathType is PathTypes.PathTypes.Absolute:
# If the path is absolute, we only have this one path to try.
if self.ConnectionAttempt != 0:
# Report the issue and return False to indicate we aren't trying to connect.
self.Logger.info(self.getLogMsgPrefix()+" failed to connect to absolute path and has nothing else to try.")
return False

# Make an absolute path
uri = path
# If this is an absolute path, there are two options:
# 1) If the path is a local hostname, we will try to manually resolve the hostname and then try that connection directly.
# This is to mitigate mDNS problems, which are described in octohttprequest, in the PathTypes.Absolute handling logic.
# Basically, mDNS is flakey and it's not supported on some OSes, so doing it ourselves fixes some of that.
# - If this is the case, we will try our manually resolved url first, and the OG second.
# 2) If the url isn't a local hostname or it fails to resolve manually, we just use the absolute URL directly.

# Try to see if this is a local hostname, if we don't already have a result.
if self.ResolvedLocalHostnameUrl is None:
# This returns None if the URL doesn't contain a local hostname or it fails to resolve.
self.ResolvedLocalHostnameUrl = MDns.Get().TryToResolveIfLocalHostnameFound(path)

if self.ResolvedLocalHostnameUrl is None:
# If self.ResolvedLocalHostnameUrl is None, there's no local hostname or it failed to resolve.
# Thus we will just try the absolute URL and nothing else.
if self.ConnectionAttempt != 0:
# Report the issue and return False to indicate we aren't trying to connect.
self.Logger.info(self.getLogMsgPrefix()+" failed to connect to absolute path and has nothing else to try.")
return False

# Use the raw absolute path.
uri = path
else:
# We have a local hostname url resolved in our string.
if self.ConnectionAttempt == 0:
# For the first attempt, try using our manually resolved URL. Since it's already resolved and might be from a cache, it's going to be faster.
uri = self.ResolvedLocalHostnameUrl
elif self.ConnectionAttempt == 1:
# For the second attempt, it means the manually resolved URL failed, so we just try the original path with no modification.
self.Logger.info(self.getLogMsgPrefix()+" failed to connect with the locally resoled hostname ("+self.ResolvedLocalHostnameUrl+"), trying the raw URL. " + path)
uri = path
else:
# We tired both, neither worked. Give up.
self.Logger.info(self.getLogMsgPrefix()+" failed to connect to manually resolved local hostname and the absolute path.")
return False
else:
raise Exception("Web stream ws helper got a open message with an unknown path type "+str(pathType))

Expand Down
4 changes: 4 additions & 0 deletions octoprint_octoeverywhere/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from .octopingpong import OctoPingPong
from .slipstream import Slipstream
from .sentry import Sentry
from .mdns import MDns
from .smartpause import SmartPause


Expand Down Expand Up @@ -164,6 +165,9 @@ def on_startup(self, host, port):
# Init the ping helper
OctoPingPong.Init(self._logger, self.get_plugin_data_folder(), printerId)

# Init the mdns helper
MDns.Init(self._logger, self.get_plugin_data_folder())

# Create the notification object now that we have the logger.
self.NotificationHandler = NotificationsHandler(self._logger, self._printer)
self.NotificationHandler.SetPrinterId(printerId)
Expand Down
10 changes: 9 additions & 1 deletion octoprint_octoeverywhere/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from .octopingpong import OctoPingPong
from .slipstream import Slipstream
from .sentry import Sentry
from .mdns import MDns
from .notificationshandler import NotificationsHandler
#from .threaddebug import ThreadDebug

Expand All @@ -36,6 +37,9 @@
PrinterId = "0QVGBOO92TENVOVN9XW5T3KT6LV1XV8ODFUEQYWQ"
PrivateKey = "uduuitfqrsstnhhjpsxhmyqwvpxgnajqqbhxferoxunusjaybodfotkupjaecnccdxzwmeajqqmjftnhoonusnjatqcryxfvrzgibouexjflbrmurkhltmsd"

# Defines a place we can write files
PluginFilePathRoot = "C:\\Users\\quinn"

# A mock of the popup UI interface.
class UiPopupInvokerStub():
def __init__(self, logger):
Expand Down Expand Up @@ -100,6 +104,10 @@ def GeneratePrinterId():
# Init Sentry, but it won't report since we are in dev mode.
Sentry.Init(logger, "dev", True)

# Init the mdns client
MDns.Init(logger, PluginFilePathRoot)
#MDns.Get().Test()

# This is a tool to help track stuck or leaked threads.
#threadDebugger = ThreadDebug()
#threadDebugger.Start(logger, 30)
Expand Down Expand Up @@ -129,7 +137,7 @@ def GeneratePrinterId():
LocalAuth.Get().SetApiKeyForTesting("SuperSecureApiKey")

# Init the ping pong helper.
OctoPingPong.Init(logger, "C:\\Users\\quinn", PrinterId)
OctoPingPong.Init(logger, PluginFilePathRoot, PrinterId)
# If we are using a local dev connection, disable this or it will overwrite.
if OctoEverywhereWsUri.startswith("ws://"):
OctoPingPong.Get().DisablePrimaryOverride()
Expand Down
Loading

0 comments on commit 378195d

Please sign in to comment.