Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
python_prctl
psutil
pycrypto
stem
32 changes: 6 additions & 26 deletions src/bitmessagemain.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@
from bmconfigparser import BMConfigParser
from debug import logger # this should go before any threads
from helper_startup import (
isOurOperatingSystemLimitedToHavingVeryFewHalfOpenConnections
isOurOperatingSystemLimitedToHavingVeryFewHalfOpenConnections,
start_proxyconfig
)
from inventory import Inventory
from knownnodes import readKnownNodes
Expand Down Expand Up @@ -168,30 +169,9 @@ def signal_handler(signum, frame):

class Main(object):
"""Main PyBitmessage class"""
@staticmethod
def start_proxyconfig(config):
"""Check socksproxytype and start any proxy configuration plugin"""
proxy_type = config.safeGet('bitmessagesettings', 'socksproxytype')
if proxy_type not in ('none', 'SOCKS4a', 'SOCKS5'):
# pylint: disable=relative-import
from plugins.plugin import get_plugin
try:
proxyconfig_start = time.time()
if not get_plugin('proxyconfig', name=proxy_type)(config):
raise TypeError
except TypeError:
logger.error(
'Failed to run proxy config plugin %s',
proxy_type, exc_info=True)
shutdown.doCleanShutdown()
sys.exit(2)
else:
logger.info(
'Started proxy config plugin %s in %s sec',
proxy_type, time.time() - proxyconfig_start)

def start(self): # pylint: disable=too-many-statements, too-many-branches, too-many-locals
def start(self):
"""Start main application"""
# pylint: disable=too-many-statements,too-many-branches,too-many-locals
_fixSocket()

config = BMConfigParser()
Expand Down Expand Up @@ -350,7 +330,7 @@ def start(self): # pylint: disable=too-many-statements, too-many-branches, to

# start network components if networking is enabled
if state.enableNetwork:
self.start_proxyconfig(config)
start_proxyconfig()
BMConnectionPool()
asyncoreThread = BMNetworkThread()
asyncoreThread.daemon = True
Expand Down Expand Up @@ -410,7 +390,7 @@ def start(self): # pylint: disable=too-many-statements, too-many-branches, to
self.stop()
elif not state.enableGUI:
from tests import core as test_core # pylint: disable=relative-import
test_core_result = test_core.run(self)
test_core_result = test_core.run()
state.enableGUI = True
self.stop()
test_core.cleanup()
Expand Down
72 changes: 41 additions & 31 deletions src/bitmessageqt/settings.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import ConfigParser
import os
import sys

Expand All @@ -16,10 +17,24 @@
import widgets
from bmconfigparser import BMConfigParser
from helper_sql import sqlExecute, sqlStoredProcedure
from helper_startup import start_proxyconfig
from network.asyncore_pollchoose import set_rates
from tr import _translate


def getSOCKSProxyType(config):
"""Get user socksproxytype setting from *config*"""
try:
result = ConfigParser.SafeConfigParser.get(
config, 'bitmessagesettings', 'socksproxytype')
except (ConfigParser.NoSectionError, ConfigParser.NoOptionError):
return
else:
if result.lower() in ('', 'none', 'false'):
result = None
return result


class SettingsDialog(QtGui.QDialog):
"""The "Settings" dialog"""
def __init__(self, parent=None, firstrun=False):
Expand All @@ -32,6 +47,16 @@ def __init__(self, parent=None, firstrun=False):
self.net_restart_needed = False
self.timer = QtCore.QTimer()

try:
import pkg_resources
except ImportError:
pass
else:
# Append proxy types defined in plugins
for ep in pkg_resources.iter_entry_points(
'bitmessage.proxyconfig'):
self.comboBoxProxyType.addItem(ep.name)

self.lineEditMaxOutboundConnections.setValidator(
QtGui.QIntValidator(0, 8, self.lineEditMaxOutboundConnections))

Expand Down Expand Up @@ -117,21 +142,11 @@ def adjust_from_config(self, config):
self.checkBoxOnionOnly.setChecked(
config.safeGetBoolean('bitmessagesettings', 'onionservicesonly'))

proxy_type = config.safeGet(
'bitmessagesettings', 'socksproxytype', 'none')
if proxy_type == 'none':
self.comboBoxProxyType.setCurrentIndex(0)
self.lineEditSocksHostname.setEnabled(False)
self.lineEditSocksPort.setEnabled(False)
self.lineEditSocksUsername.setEnabled(False)
self.lineEditSocksPassword.setEnabled(False)
self.checkBoxAuthentication.setEnabled(False)
self.checkBoxSocksListen.setEnabled(False)
self.checkBoxOnionOnly.setEnabled(False)
elif proxy_type == 'SOCKS4a':
self.comboBoxProxyType.setCurrentIndex(1)
elif proxy_type == 'SOCKS5':
self.comboBoxProxyType.setCurrentIndex(2)
self._proxy_type = getSOCKSProxyType(config)
self.comboBoxProxyType.setCurrentIndex(
0 if not self._proxy_type
else self.comboBoxProxyType.findText(self._proxy_type))
self.comboBoxProxyTypeChanged(self.comboBoxProxyType.currentIndex())

self.lineEditSocksHostname.setText(
config.get('bitmessagesettings', 'sockshostname'))
Expand Down Expand Up @@ -219,7 +234,7 @@ def comboBoxProxyTypeChanged(self, comboBoxIndex):
self.checkBoxAuthentication.setEnabled(False)
self.checkBoxSocksListen.setEnabled(False)
self.checkBoxOnionOnly.setEnabled(False)
elif comboBoxIndex in (1, 2):
else:
self.lineEditSocksHostname.setEnabled(True)
self.lineEditSocksPort.setEnabled(True)
self.checkBoxAuthentication.setEnabled(True)
Expand Down Expand Up @@ -321,27 +336,22 @@ def accept(self):
upnpThread = upnp.uPnPThread()
upnpThread.start()

proxy_type = self.config.safeGet(
'bitmessagesettings', 'socksproxytype', 'none')
if (
proxy_type == 'none' and
self.comboBoxProxyType.currentText()[0:5] == 'SOCKS' and
shared.statusIconColor != 'red'
):
self.net_restart_needed = True
if (
proxy_type[0:5] == 'SOCKS' and
self.comboBoxProxyType.currentText()[0:5] != 'SOCKS'
):
proxytype_index = self.comboBoxProxyType.currentIndex()
if proxytype_index == 0:
if self._proxy_type and shared.statusIconColor != 'red':
self.net_restart_needed = True
elif self.comboBoxProxyType.currentText() != self._proxy_type:
self.net_restart_needed = True
self.parent.statusbar.clearMessage()

self.config.set(
'bitmessagesettings', 'socksproxytype',
str(self.comboBoxProxyType.currentText())
if self.comboBoxProxyType.currentText()[0:5] == 'SOCKS'
else 'none'
'none' if self.comboBoxProxyType.currentIndex() == 0
else str(self.comboBoxProxyType.currentText())
)
if proxytype_index > 2: # last literal proxytype in ui
start_proxyconfig()

self.config.set('bitmessagesettings', 'socksauthentication', str(
self.checkBoxAuthentication.isChecked()))
self.config.set('bitmessagesettings', 'sockshostname', str(
Expand Down
4 changes: 2 additions & 2 deletions src/bitmessageqt/settings.ui
Original file line number Diff line number Diff line change
Expand Up @@ -419,12 +419,12 @@
</item>
<item>
<property name="text">
<string>SOCKS4a</string>
<string notr="true">SOCKS4a</string>
</property>
</item>
<item>
<property name="text">
<string>SOCKS5</string>
<string notr="true">SOCKS5</string>
</property>
</item>
</widget>
Expand Down
4 changes: 2 additions & 2 deletions src/bitmessageqt/support.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import paths
import proofofwork
from pyelliptic.openssl import OpenSSL
from settings import getSOCKSProxyType
import queues
import network.stats
import state
Expand Down Expand Up @@ -118,8 +119,7 @@ def createSupportMessage(myapp):
BMConfigParser().safeGet('bitmessagesettings', 'opencl')
) if openclEnabled() else "None"
locale = getTranslationLanguage()
socks = BMConfigParser().safeGet(
'bitmessagesettings', 'socksproxytype', "N/A")
socks = getSOCKSProxyType(BMConfigParser()) or "N/A"
upnp = BMConfigParser().safeGet('bitmessagesettings', 'upnp', "N/A")
connectedhosts = len(network.stats.connectedHostsList())

Expand Down
49 changes: 41 additions & 8 deletions src/helper_startup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
Startup operations.
"""
# pylint: disable=too-many-branches,too-many-statements
from __future__ import print_function

import logging
import os
import platform
import sys
import time
from distutils.version import StrictVersion

import defaults
Expand All @@ -15,6 +16,13 @@
import state
from bmconfigparser import BMConfigParser

try:
from plugins.plugin import get_plugin
except ImportError:
get_plugin = None


logger = logging.getLogger('default')

# The user may de-select Portable Mode in the settings if they want
# the config files to stay in the application data folder.
Expand All @@ -30,14 +38,14 @@ def loadConfig():
needToCreateKeysFile = config.safeGet(
'bitmessagesettings', 'settingsversion') is None
if not needToCreateKeysFile:
print(
logger.info(

@PeterSurda PeterSurda Nov 16, 2019 •

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.

Good, these are the few places where I left print due to initialisation order, which you now fixed.

'Loading config files from directory specified'
' on startup: %s' % state.appdata)
' on startup: %s', state.appdata)
else:
config.read(paths.lookupExeFolder() + 'keys.dat')
try:
config.get('bitmessagesettings', 'settingsversion')
print('Loading config files from same directory as program.')
logger.info('Loading config files from same directory as program.')
needToCreateKeysFile = False
state.appdata = paths.lookupExeFolder()
except:
Expand All @@ -48,7 +56,8 @@ def loadConfig():
needToCreateKeysFile = config.safeGet(
'bitmessagesettings', 'settingsversion') is None
if not needToCreateKeysFile:
print('Loading existing config files from', state.appdata)
logger.info(
'Loading existing config files from %s', state.appdata)

if needToCreateKeysFile:

Expand Down Expand Up @@ -103,9 +112,10 @@ def loadConfig():
# Just use the same directory as the program and forget about
# the appdata folder
state.appdata = ''
print('Creating new config files in same directory as program.')
logger.info(
'Creating new config files in same directory as program.')
else:
print('Creating new config files in', state.appdata)
logger.info('Creating new config files in %s', state.appdata)
if not os.path.exists(state.appdata):
os.makedirs(state.appdata)
if not sys.platform.startswith('win'):
Expand Down Expand Up @@ -255,7 +265,7 @@ def updateConfig():
'bitmessagesettings', 'hidetrayconnectionnotifications', 'false')
if config.safeGetInt('bitmessagesettings', 'maxoutboundconnections') < 1:
config.set('bitmessagesettings', 'maxoutboundconnections', '8')
print('WARNING: your maximum outbound connections must be a number.')
logger.warning('Your maximum outbound connections must be a number.')

# TTL is now user-specifiable. Let's add an option to save
# whatever the user selects.
Expand All @@ -278,3 +288,26 @@ def isOurOperatingSystemLimitedToHavingVeryFewHalfOpenConnections():
return False
except Exception:
pass


def start_proxyconfig():
"""Check socksproxytype and start any proxy configuration plugin"""
if not get_plugin:
return
config = BMConfigParser()
proxy_type = config.safeGet('bitmessagesettings', 'socksproxytype')
if proxy_type and proxy_type not in ('none', 'SOCKS4a', 'SOCKS5'):
try:
proxyconfig_start = time.time()
if not get_plugin('proxyconfig', name=proxy_type)(config):
raise TypeError()
except TypeError:
# cannot import shutdown here ):
logger.error(
'Failed to run proxy config plugin %s',
proxy_type, exc_info=True)
os._exit(0) # pylint: disable=protected-access
else:
logger.info(
'Started proxy config plugin %s in %s sec',
proxy_type, time.time() - proxyconfig_start)
7 changes: 7 additions & 0 deletions src/plugins/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"""
Simple plugin system based on setuptools
----------------------------------------


"""
# .. include:: pybitmessage.plugins.plugin.rst
27 changes: 20 additions & 7 deletions src/plugins/plugin.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
# -*- coding: utf-8 -*-
"""
src/plugins/plugin.py
===================================
Operating with plugins
"""
import logging

import pkg_resources


logger = logging.getLogger('default')


def get_plugins(group, point='', name=None, fallback=None):
"""
Iterate through plugins (`connect_plugin` attribute of entry point)
which name starts with `point` or equals to `name`.
If `fallback` kwarg specified, plugin with that name yield last.
:param str group: plugin group
:param str point: plugin name prefix
:param name: exact plugin name
:param fallback: fallback plugin name

Iterate through plugins (``connect_plugin`` attribute of entry point)
which name starts with ``point`` or equals to ``name``.
If ``fallback`` kwarg specified, plugin with that name yield last.
"""
for ep in pkg_resources.iter_entry_points('bitmessage.' + group):
if name and ep.name == name or ep.name.startswith(point):
if name and ep.name == name or not point or ep.name.startswith(point):
try:
plugin = ep.load().connect_plugin
if ep.name == fallback:
Expand All @@ -25,6 +34,8 @@ def get_plugins(group, point='', name=None, fallback=None):
ValueError,
pkg_resources.DistributionNotFound,
pkg_resources.UnknownExtra):
logger.debug(
'Problem while loading %s', ep.name, exc_info=True)
continue
try:
yield _fallback
Expand All @@ -33,6 +44,8 @@ def get_plugins(group, point='', name=None, fallback=None):


def get_plugin(*args, **kwargs):
"""Returns first available plugin `from get_plugins()` if any."""
"""
:return: first available plugin from :func:`get_plugins` if any.
"""
for plugin in get_plugins(*args, **kwargs):
return plugin
Loading