Skip to content

Commit

Permalink
ui: allow to use multiple protobuffer versions
Browse files Browse the repository at this point in the history
Protobuffers compiled with protobuf < 3.20.0 are incompatible with
protobuf >= 4.0.0:
https://github.com/evilsocket/opensnitch/wiki/GUI-known-problems#gui-does-not-show-up

This has been a source of problems for some users (#1214, #647), and
in some distributions, previous protobuffer does no longer work due to
incompatibility with the protobuf package version installed
(OpenSuse Tumbleweed).

So in order to solve this issue, we provide several protobuffers,
for old and new protobuf versions:
proto/ui_pb2* for protobuf >= 4.0.0
proto/pre3200/ui_pb2* for protobuf >= 3.6.0 and < 3.20.0

To avoid import errors, each protobuffer must be placed in its own
directory, and the name of the protobuffer files must be named with
the syntax <prefix>_pb2.py/<prefix>_pb2_grpc.py:
  ui_pb2.py and ui_pb2_grpc.py

The default compiled protobuffer will be opensnitch/proto/ui_*.py
instead of opensnitch/ui_*.py
  • Loading branch information
gustavo-iniguez-goya committed Dec 26, 2024
1 parent 4282fe4 commit f91f1a9
Show file tree
Hide file tree
Showing 22 changed files with 2,769 additions and 30 deletions.
1 change: 1 addition & 0 deletions ui/MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
recursive-include opensnitch/proto *
recursive-include opensnitch/res *
recursive-include opensnitch/i18n *.qm
recursive-include opensnitch/database/migrations *.sql
Expand Down
7 changes: 4 additions & 3 deletions ui/bin/opensnitch-ui
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,10 @@ from opensnitch.service import UIService
from opensnitch.config import Config
from opensnitch.utils import Themes, Utils, Versions, Message
from opensnitch.utils.xdg import xdg_opensnitch_dir, xdg_current_session
import opensnitch.ui_pb2
from opensnitch.ui_pb2_grpc import add_UIServicer_to_server

from opensnitch import auth
import opensnitch.proto as proto
ui_pb2, ui_pb2_grpc = proto.import_()

app_id = os.path.join(xdg_opensnitch_dir, "io.github.evilsocket.opensnitch")

Expand Down Expand Up @@ -203,7 +204,7 @@ Examples:
('grpc.max_receive_message_length', maxmsglen),
))

add_UIServicer_to_server(service, server)
ui_pb2_grpc.add_UIServicer_to_server(service, server)

auth_type = auth.Simple
if args.socket_auth != None:
Expand Down
3 changes: 2 additions & 1 deletion ui/opensnitch/dialogs/firewall.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@
from opensnitch.config import Config
from opensnitch.nodes import Nodes
from opensnitch.dialogs.firewall_rule import FwRuleDialog
from opensnitch import ui_pb2
import opensnitch.firewall as Fw
import opensnitch.firewall.profiles as FwProfiles

import opensnitch.proto as proto
ui_pb2, ui_pb2_grpc = proto.import_()

DIALOG_UI_PATH = "%s/../res/firewall.ui" % os.path.dirname(sys.modules[__name__].__file__)
class FirewallDialog(QtWidgets.QDialog, uic.loadUiType(DIALOG_UI_PATH)[0]):
Expand Down
3 changes: 2 additions & 1 deletion ui/opensnitch/dialogs/firewall_rule.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@
from opensnitch.config import Config
from opensnitch.nodes import Nodes
from opensnitch.utils import NetworkServices, NetworkInterfaces, QuickHelp, Icons, Utils
from opensnitch import ui_pb2
import opensnitch.firewall as Fw
from opensnitch.firewall.utils import Utils as FwUtils

import opensnitch.proto as proto
ui_pb2, ui_pb2_grpc = proto.import_()

DIALOG_UI_PATH = "%s/../res/firewall_rule.ui" % os.path.dirname(sys.modules[__name__].__file__)
class FwRuleDialog(QtWidgets.QDialog, uic.loadUiType(DIALOG_UI_PATH)[0]):
Expand Down
4 changes: 3 additions & 1 deletion ui/opensnitch/dialogs/preferences.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
from opensnitch.utils.xdg import Autostart
from opensnitch.notifications import DesktopNotifications

from opensnitch import ui_pb2, auth
from opensnitch import auth
import opensnitch.proto as proto
ui_pb2, ui_pb2_grpc = proto.import_()

DIALOG_UI_PATH = "%s/../res/preferences.ui" % os.path.dirname(sys.modules[__name__].__file__)
class PreferencesDialog(QtWidgets.QDialog, uic.loadUiType(DIALOG_UI_PATH)[0]):
Expand Down
4 changes: 3 additions & 1 deletion ui/opensnitch/dialogs/processdetails.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

from PyQt5 import QtCore, QtGui, uic, QtWidgets

from opensnitch import ui_pb2
import opensnitch.proto as proto
ui_pb2, ui_pb2_grpc = proto.import_()

from opensnitch.nodes import Nodes
from opensnitch.desktop_parser import LinuxDesktopParser
from opensnitch.utils import Message, Icons
Expand Down
3 changes: 2 additions & 1 deletion ui/opensnitch/dialogs/prompt.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
from opensnitch.actions import Actions
from opensnitch.rules import Rules, Rule

from opensnitch import ui_pb2
import opensnitch.proto as proto
ui_pb2, ui_pb2_grpc = proto.import_()

DIALOG_UI_PATH = "%s/../res/prompt.ui" % os.path.dirname(sys.modules[__name__].__file__)
class PromptDialog(QtWidgets.QDialog, uic.loadUiType(DIALOG_UI_PATH)[0]):
Expand Down
4 changes: 3 additions & 1 deletion ui/opensnitch/dialogs/ruleseditor.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
import sys
import os
import pwd
from opensnitch import ui_pb2
import time
import ipaddress

import opensnitch.proto as proto
ui_pb2, ui_pb2_grpc = proto.import_()

from opensnitch.config import Config
from opensnitch.nodes import Nodes
from opensnitch.database import Database
Expand Down
4 changes: 3 additions & 1 deletion ui/opensnitch/dialogs/stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
from PyQt5 import QtCore, QtGui, uic, QtWidgets
from PyQt5.QtCore import QCoreApplication as QC

from opensnitch import ui_pb2
from opensnitch.config import Config
from opensnitch.version import version
from opensnitch.nodes import Nodes
Expand All @@ -27,6 +26,9 @@
from opensnitch.actions import Actions
from opensnitch.rules import Rule, Rules

import opensnitch.proto as proto
ui_pb2, ui_pb2_grpc = proto.import_()

DIALOG_UI_PATH = "%s/../res/stats.ui" % os.path.dirname(sys.modules[__name__].__file__)
class StatsDialog(QtWidgets.QDialog, uic.loadUiType(DIALOG_UI_PATH)[0]):

Expand Down
3 changes: 2 additions & 1 deletion ui/opensnitch/firewall/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from PyQt5.QtCore import QObject, QCoreApplication as QC
from google.protobuf import json_format
from opensnitch import ui_pb2
import opensnitch.proto as proto
ui_pb2, ui_pb2_grpc = proto.import_()

from opensnitch.nodes import Nodes
from .enums import *
Expand Down
4 changes: 3 additions & 1 deletion ui/opensnitch/firewall/chains.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from opensnitch import ui_pb2
import opensnitch.proto as proto
ui_pb2, ui_pb2_grpc = proto.import_()

from .enums import *

class Chains():
Expand Down
4 changes: 3 additions & 1 deletion ui/opensnitch/firewall/exprs.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@

from opensnitch import ui_pb2
import opensnitch.proto as proto
ui_pb2, ui_pb2_grpc = proto.import_()

from .enums import *

class Expr():
Expand Down
4 changes: 3 additions & 1 deletion ui/opensnitch/firewall/rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
from google.protobuf.json_format import MessageToJson
import uuid

from opensnitch import ui_pb2
import opensnitch.proto as proto
ui_pb2, ui_pb2_grpc = proto.import_()

from .enums import Operator
from .exprs import ExprLog

Expand Down
4 changes: 3 additions & 1 deletion ui/opensnitch/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@
import time
import json

from opensnitch import ui_pb2
from opensnitch.database import Database
from opensnitch.config import Config
from opensnitch.utils import NetworkInterfaces
from opensnitch.rules import Rules

import opensnitch.proto as proto
ui_pb2, ui_pb2_grpc = proto.import_()

class Nodes(QObject):
__instance = None
nodesUpdated = pyqtSignal(int) # total
Expand Down
57 changes: 57 additions & 0 deletions ui/opensnitch/proto/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Copyright (C) 2018 Simone Margaritelli
# 2019-2025 Gustavo Iñiguez Goia
#
# This file is part of OpenSnitch.
#
# OpenSnitch is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# OpenSnitch is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with OpenSnitch. If not, see <http://www.gnu.org/licenses/>.

from packaging.version import Version
import importlib
from opensnitch.utils import Versions

# Protobuffers compiled with protobuf < 3.20.0 are incompatible with
# protobuf >= 4.0.0
# https://github.com/evilsocket/opensnitch/wiki/GUI-known-problems#gui-does-not-show-up
#
# In order to solve this issue, we provide several protobuffers:
# proto.ui_pb2* for protobuf >= 4.0.0
# proto.pre3200.ui_pb2* for protobuf >= 3.6.0 and < 3.20.0
#
# To avoid import errors, each protobuffer must be placed in its own directory,
# and the name of the protobuffer files must be named with the syntax
# <prefix>_pb2.py/<prefix>_pb2_grpc.py:
# ui_pb2.py and ui_pb2_grpc.py

default_pb = "opensnitch.proto.ui_pb2"
default_grpc = "opensnitch.proto.ui_pb2_grpc"
old_pb = "opensnitch.proto.pre3200.ui_pb2"
old_grpc = "opensnitch.proto.pre3200.ui_pb2_grpc"

def import_():
"""load the protobuffer needed based on the grpc and protobuffer version
installed in the system.
"""
try:
gui_version, grpc_version, proto_version = Versions.get()
proto_ver = default_pb
grpc_ver = default_grpc

if Version(proto_version) < Version("3.20.0"):
proto_ver = old_pb
grpc_ver = old_grpc

return importlib.import_module(proto_ver), importlib.import_module(grpc_ver)
except Exception as e:
print("error importing protobuffer: ", repr(e))
return importlib.import_module(default_pb, default_grpc)
Loading

0 comments on commit f91f1a9

Please sign in to comment.