Merge lp:~alecu/ubuntuone-client/proxy-tunnel-auth into lp:ubuntuone-client

Proposed by Alejandro J. Cura
Status: Merged
Approved by: Alejandro J. Cura
Approved revision: 1239
Merged at revision: 1211
Proposed branch: lp:~alecu/ubuntuone-client/proxy-tunnel-auth
Merge into: lp:ubuntuone-client
Diff against target: 417 lines (+212/-24)
3 files modified
tests/proxy/test_tunnel_server.py (+128/-3)
ubuntuone/proxy/common.py (+0/-2)
ubuntuone/proxy/tunnel_server.py (+84/-19)
To merge this branch: bzr merge lp:~alecu/ubuntuone-client/proxy-tunnel-auth
Reviewer Review Type Date Requested Status
Diego Sarmentero (community) Approve
Manuel de la Peña (community) Approve
Review via email: mp+97763@code.launchpad.net

Commit message

- Use proxy credentials from the keyring (LP: #929207)

Description of the change

- Use proxy credentials from the keyring (LP: #929207)

To post a comment you must log in.
1238. By Alejandro J. Cura

merged from trunk

Revision history for this message
Manuel de la Peña (mandel) wrote :

Everything looks good, here are some small comments:

return QNetworkProxy(QNetworkProxy.NoProxy)

As far as I understand this, the tunnel will use no proxy ignoring the application level proxy. I think it might be more appropriate to return QNetworkProxy(QNetworkProxy.DefaultProxy). Returning default proxy will make the code use a higher alternative, for example the application-level proxy settings. I know that we are using build_proxy to set the application level proxy, but I want to be 100% saure that we do the right thing, also when the proxy is the application level proxy DefaultProxy and NoProxy have the same meaning therefore in our current code we will be using the same.

This is just a save guard, so is certainly not blocking the code from landing.

Maybe we could ensure that self.proxy_domain is always a python string and not a QString in memory, it would be as simple as changing:

340 + self.proxy_domain = proxy.hostName()

for

340 + self.proxy_domain = str(proxy.hostName())

I think it would be less error prone, what is you opinion?

I'll approve even with the above comments.

review: Approve
Revision history for this message
Alejandro J. Cura (alecu) wrote :

> Everything looks good, here are some small comments:
>
> return QNetworkProxy(QNetworkProxy.NoProxy)
>
> As far as I understand this, the tunnel will use no proxy ignoring the
> application level proxy. I think it might be more appropriate to return
> QNetworkProxy(QNetworkProxy.DefaultProxy). Returning default proxy will make
> the code use a higher alternative, for example the application-level proxy
> settings. I know that we are using build_proxy to set the application level
> proxy, but I want to be 100% saure that we do the right thing, also when the
> proxy is the application level proxy DefaultProxy and NoProxy have the same
> meaning therefore in our current code we will be using the same.

I've fixed this, thanks for the suggestion.

> Maybe we could ensure that self.proxy_domain is always a python string and not
> a QString in memory, it would be as simple as changing:
>
> 340 + self.proxy_domain = proxy.hostName()
>
> for
>
> 340 + self.proxy_domain = str(proxy.hostName())
>
> I think it would be less error prone, what is you opinion?

I don't think that's needed, since most uses of self.proxy_domain are for comparing again proxy.hostName(). In the only place where it's sent from the containing object to the keyring.get_credentials method it is already being transformed with str.

I'm now pushing the branch with the first fix requested.

Thanks for the review!

1239. By Alejandro J. Cura

Change fallback from NoProxy to DefaultProxy.

Revision history for this message
Diego Sarmentero (diegosarmentero) wrote :

I have this failure running the tests:

[ERROR]
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/twisted/internet/defer.py", line 1039, in _inlineCallbacks
    result = g.send(result)
  File "/media/gato/proyectos/canonical/ubuntuone-client-alecu-last/ubuntuone/syncdaemon/action_queue.py", line 839, in get_webclient
    oauth_sign_plain=True)
exceptions.TypeError: __init__() got an unexpected keyword argument 'connector'

tests.syncdaemon.test_action_queue.BasicTests.test_get_webclient

review: Needs Fixing
Revision history for this message
Alejandro J. Cura (alecu) wrote :

> I have this failure running the tests:
>
> [ERROR]
> Traceback (most recent call last):
> File "/usr/lib/python2.7/dist-packages/twisted/internet/defer.py", line
> 1039, in _inlineCallbacks
> result = g.send(result)
> File "/media/gato/proyectos/canonical/ubuntuone-client-alecu-
> last/ubuntuone/syncdaemon/action_queue.py", line 839, in get_webclient
> oauth_sign_plain=True)
> exceptions.TypeError: __init__() got an unexpected keyword argument
> 'connector'
>
> tests.syncdaemon.test_action_queue.BasicTests.test_get_webclient

Looks like the ussoc you are using is not trunk.
Try updating nightlies or configuring this branch using "--with-sso=/path/to/sso/trunk"

Revision history for this message
Diego Sarmentero (diegosarmentero) wrote :

+1

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'tests/proxy/test_tunnel_server.py'
--- tests/proxy/test_tunnel_server.py 2012-03-14 17:38:31 +0000
+++ tests/proxy/test_tunnel_server.py 2012-03-16 13:44:19 +0000
@@ -21,6 +21,7 @@
21from twisted.internet import defer, protocol, reactor21from twisted.internet import defer, protocol, reactor
22from twisted.trial.unittest import TestCase22from twisted.trial.unittest import TestCase
23from PyQt4.QtCore import QCoreApplication23from PyQt4.QtCore import QCoreApplication
24from PyQt4.QtNetwork import QAuthenticator
24from ubuntuone.devtools.testcases.squid import SquidTestCase25from ubuntuone.devtools.testcases.squid import SquidTestCase
2526
26from tests.proxy import (27from tests.proxy import (
@@ -51,6 +52,11 @@
51SAMPLE_HOST = "samplehost.com"52SAMPLE_HOST = "samplehost.com"
52SAMPLE_PORT = 44353SAMPLE_PORT = 443
5354
55FAKE_CREDS = {
56 "username": "rhea",
57 "password": "caracolcaracola",
58}
59
5460
55class DisconnectingProtocol(protocol.Protocol):61class DisconnectingProtocol(protocol.Protocol):
56 """A protocol that just disconnects."""62 """A protocol that just disconnects."""
@@ -154,9 +160,16 @@
154160
155 protocol = None161 protocol = None
156 connection_result = defer.succeed(True)162 connection_result = defer.succeed(True)
163 credentials = None
164 check_credentials = False
165 proxy_domain = None
157166
158 def connect(self, hostport):167 def connect(self, hostport):
159 """Establish a connection with the other end."""168 """Establish a connection with the other end."""
169 if (self.check_credentials and
170 self.protocol.proxy_credentials != FAKE_CREDS):
171 self.proxy_domain = "fake domain"
172 return defer.fail(tunnel_server.ProxyAuthenticationError())
160 return self.connection_result173 return self.connection_result
161174
162 def write(self, data):175 def write(self, data):
@@ -167,6 +180,10 @@
167 def stop(self):180 def stop(self):
168 """Stop this fake client."""181 """Stop this fake client."""
169182
183 def close(self):
184 """Reset this client."""
185
186
170187
171class ServerTunnelProtocolTestCase(SquidTestCase):188class ServerTunnelProtocolTestCase(SquidTestCase):
172 """Tests for the ServerTunnelProtocol."""189 """Tests for the ServerTunnelProtocol."""
@@ -243,6 +260,17 @@
243 self.proto.header_line("key: host:port")260 self.proto.header_line("key: host:port")
244 self.assertIn("key", dict(self.proto.received_headers))261 self.assertIn("key", dict(self.proto.received_headers))
245262
263 @defer.inlineCallbacks
264 def test_keyring_credentials_are_retried(self):
265 """Wrong credentials are retried with values from keyring."""
266 self.fake_client.check_credentials = True
267 self.patch(self.proto, "error_response",
268 lambda code, desc: self.fail(desc))
269 self.proto.proxy_domain = "xxx"
270 self.patch(tunnel_server.Keyring, "get_credentials",
271 lambda _, domain: defer.succeed(FAKE_CREDS))
272 yield self.proto.headers_done()
273
246274
247class FakeServerTunnelProtocol(object):275class FakeServerTunnelProtocol(object):
248 """A fake ServerTunnelProtocol."""276 """A fake ServerTunnelProtocol."""
@@ -250,6 +278,7 @@
250 def __init__(self):278 def __init__(self):
251 """Initialize this fake tunnel."""279 """Initialize this fake tunnel."""
252 self.response_received = defer.Deferred()280 self.response_received = defer.Deferred()
281 self.proxy_credentials = None
253282
254 def response_data_received(self, data):283 def response_data_received(self, data):
255 """Fire the response deferred."""284 """Fire the response deferred."""
@@ -259,6 +288,55 @@
259 def remote_disconnected(self):288 def remote_disconnected(self):
260 """The remote server disconnected."""289 """The remote server disconnected."""
261290
291 def proxy_auth_required(self, proxy, authenticator):
292 """Proxy credentials are needed."""
293 if self.proxy_credentials:
294 authenticator.setUser(self.proxy_credentials["username"])
295 authenticator.setPassword(self.proxy_credentials["password"])
296
297
298class BuildProxyTestCase(TestCase):
299 """Tests for the build_proxy function."""
300
301 def test_socks_is_preferred(self):
302 """Socks overrides all protocols."""
303 settings = {
304 "http": {"host": "httphost", "port": 3128},
305 "https": {"host": "httpshost", "port": 3129},
306 "socks": {"host": "sockshost", "port": 1080},
307 }
308 proxy = tunnel_server.build_proxy(settings)
309 self.assertEqual(proxy.type(), proxy.Socks5Proxy)
310 self.assertEqual(proxy.hostName(), "sockshost")
311 self.assertEqual(proxy.port(), 1080)
312
313 def test_https_beats_http(self):
314 """HTTPS wins over HTTP, since all of SD traffic is https."""
315 settings = {
316 "http": {"host": "httphost", "port": 3128},
317 "https": {"host": "httpshost", "port": 3129},
318 }
319 proxy = tunnel_server.build_proxy(settings)
320 self.assertEqual(proxy.type(), proxy.HttpProxy)
321 self.assertEqual(proxy.hostName(), "httpshost")
322 self.assertEqual(proxy.port(), 3129)
323
324 def test_http_if_no_other_choice(self):
325 """Finally, we use the host configured for HTTP."""
326 settings = {
327 "http": {"host": "httphost", "port": 3128},
328 }
329 proxy = tunnel_server.build_proxy(settings)
330 self.assertEqual(proxy.type(), proxy.HttpProxy)
331 self.assertEqual(proxy.hostName(), "httphost")
332 self.assertEqual(proxy.port(), 3128)
333
334 def test_use_noproxy_as_fallback(self):
335 """If nothing useful, revert to no proxy."""
336 settings = {}
337 proxy = tunnel_server.build_proxy(settings)
338 self.assertEqual(proxy.type(), proxy.DefaultProxy)
339
262340
263class RemoteSocketTestCase(SquidTestCase):341class RemoteSocketTestCase(SquidTestCase):
264 """Tests for the client that connects to the other side."""342 """Tests for the client that connects to the other side."""
@@ -276,8 +354,9 @@
276354
277 self.addCleanup(tunnel_server.QNetworkProxy.setApplicationProxy,355 self.addCleanup(tunnel_server.QNetworkProxy.setApplicationProxy,
278 tunnel_server.QNetworkProxy.applicationProxy())356 tunnel_server.QNetworkProxy.applicationProxy())
279 tunnel_server.QNetworkProxy.setApplicationProxy(357 settings = {"http": self.get_proxy_settings()}
280 tunnel_server.build_proxy(self.get_proxy_settings()))358 proxy = tunnel_server.build_proxy(settings)
359 tunnel_server.QNetworkProxy.setApplicationProxy(proxy)
281360
282 def test_invalid_port(self):361 def test_invalid_port(self):
283 """A request with an invalid port fails with a 400."""362 """A request with an invalid port fails with a 400."""
@@ -365,6 +444,52 @@
365444
366 get_proxy_settings = RemoteSocketTestCase.get_auth_proxy_settings445 get_proxy_settings = RemoteSocketTestCase.get_auth_proxy_settings
367446
447 @defer.inlineCallbacks
448 def test_proxy_authentication_error(self):
449 """The proxy credentials were wrong on purpose."""
450 settings = {"http": self.get_proxy_settings()}
451 settings["http"]["password"] = "wrong password!!!"
452 proxy = tunnel_server.build_proxy(settings)
453 tunnel_server.QNetworkProxy.setApplicationProxy(proxy)
454 fake_protocol = FakeServerTunnelProtocol()
455 client = tunnel_server.RemoteSocket(fake_protocol)
456 self.addCleanup(client.stop)
457 url = urlparse(self.dest_url)
458 yield self.assertFailure(client.connect(url.netloc),
459 tunnel_server.ProxyAuthenticationError)
460
461 @defer.inlineCallbacks
462 def test_proxy_nobody_listens(self):
463 """The proxy settings point to a proxy that's unreachable."""
464 settings = dict(http={
465 "host": "127.0.0.1",
466 "port": 83, # unused port according to /etc/services
467 })
468 proxy = tunnel_server.build_proxy(settings)
469 tunnel_server.QNetworkProxy.setApplicationProxy(proxy)
470 fake_protocol = FakeServerTunnelProtocol()
471 client = tunnel_server.RemoteSocket(fake_protocol)
472 self.addCleanup(client.stop)
473 url = urlparse(self.dest_url)
474 yield self.assertFailure(client.connect(url.netloc),
475 tunnel_server.ConnectionError)
476
477 def test_use_credentials(self):
478 """The credentials are used if present."""
479 fake_protocol = FakeServerTunnelProtocol()
480 client = tunnel_server.RemoteSocket(fake_protocol)
481 proxy = tunnel_server.build_proxy(FAKE_SETTINGS)
482 authenticator = QAuthenticator()
483
484 client.proxyAuthenticationRequired.emit(proxy, authenticator)
485 self.assertEqual(proxy.user(), "")
486 self.assertEqual(proxy.password(), "")
487 fake_protocol.proxy_credentials = FAKE_CREDS
488
489 client.proxyAuthenticationRequired.emit(proxy, authenticator)
490 self.assertEqual(authenticator.user(), FAKE_CREDS["username"])
491 self.assertEqual(authenticator.password(), FAKE_CREDS["password"])
492
368493
369class FakeNetworkProxyFactoryClass(object):494class FakeNetworkProxyFactoryClass(object):
370 """A fake QNetworkProxyFactory."""495 """A fake QNetworkProxyFactory."""
@@ -375,7 +500,7 @@
375 if enabled:500 if enabled:
376 self.proxy_type = tunnel_server.QNetworkProxy.HttpProxy501 self.proxy_type = tunnel_server.QNetworkProxy.HttpProxy
377 else:502 else:
378 self.proxy_type = tunnel_server.QNetworkProxy.NoProxy503 self.proxy_type = tunnel_server.QNetworkProxy.DefaultProxy
379504
380 def type(self):505 def type(self):
381 """Return the proxy type configured."""506 """Return the proxy type configured."""
382507
=== modified file 'ubuntuone/proxy/common.py'
--- ubuntuone/proxy/common.py 2012-03-09 22:36:14 +0000
+++ ubuntuone/proxy/common.py 2012-03-16 13:44:19 +0000
@@ -56,5 +56,3 @@
56 def format_headers(self, headers):56 def format_headers(self, headers):
57 """Format some headers as a few response lines."""57 """Format some headers as a few response lines."""
58 return "".join("%s: %s" % item + CRLF for item in headers.items())58 return "".join("%s: %s" % item + CRLF for item in headers.items())
59
60
6159
=== modified file 'ubuntuone/proxy/tunnel_server.py'
--- ubuntuone/proxy/tunnel_server.py 2012-03-14 17:38:31 +0000
+++ ubuntuone/proxy/tunnel_server.py 2012-03-16 13:44:19 +0000
@@ -44,6 +44,7 @@
44from twisted.internet import defer, interfaces44from twisted.internet import defer, interfaces
45from zope.interface import implements45from zope.interface import implements
4646
47from ubuntu_sso.keyring import Keyring
47from ubuntu_sso.utils.webclient import gsettings48from ubuntu_sso.utils.webclient import gsettings
48from ubuntuone.proxy.common import BaseTunnelProtocol, CRLF, TUNNEL_PORT_LABEL49from ubuntuone.proxy.common import BaseTunnelProtocol, CRLF, TUNNEL_PORT_LABEL
49from ubuntuone.proxy.logger import logger50from ubuntuone.proxy.logger import logger
@@ -64,17 +65,25 @@
64 """Credentials mismatch going thru a proxy."""65 """Credentials mismatch going thru a proxy."""
6566
6667
67def build_proxy(settings):68def build_proxy(settings_groups):
68 """Create a QNetworkProxy from these settings."""69 """Create a QNetworkProxy from these settings."""
69 if "host" not in settings or "port" not in settings:70 proxy_groups = [
70 return QNetworkProxy(QNetworkProxy.NoProxy)71 ("socks", QNetworkProxy.Socks5Proxy),
71 else:72 ("https", QNetworkProxy.HttpProxy),
72 # TODO: add authentication here, to replace the empty user/pass73 ("http", QNetworkProxy.HttpProxy),
73 return QNetworkProxy(QNetworkProxy.HttpProxy,74 ]
74 hostName=settings.get("host", ""),75 for group, proxy_type in proxy_groups:
75 port=settings.get("port", 0),76 if group not in settings_groups:
76 user=settings.get("username", ""),77 continue
77 password=settings.get("password", ""))78 settings = settings_groups[group]
79 if "host" in settings and "port" in settings:
80 return QNetworkProxy(proxy_type,
81 hostName=settings.get("host", ""),
82 port=settings.get("port", 0),
83 user=settings.get("username", ""),
84 password=settings.get("password", ""))
85 logger.error("No proxy correctly configured.")
86 return QNetworkProxy(QNetworkProxy.DefaultProxy)
7887
7988
80class RemoteSocket(QTcpSocket):89class RemoteSocket(QTcpSocket):
@@ -84,13 +93,14 @@
84 """Initialize this object."""93 """Initialize this object."""
85 super(RemoteSocket, self).__init__()94 super(RemoteSocket, self).__init__()
86 self.protocol = tunnel_protocol95 self.protocol = tunnel_protocol
87 self.disconnected.connect(self.handle_disconnected)
88 self.connected_d = defer.Deferred()96 self.connected_d = defer.Deferred()
89 self.connected.connect(self.handle_connected)97 self.connected.connect(self.handle_connected)
98 self.proxyAuthenticationRequired.connect(self.handle_auth_required)
90 self.buffered_data = []99 self.buffered_data = []
91100
92 def handle_connected(self):101 def handle_connected(self):
93 """When connected, send all pending data."""102 """When connected, send all pending data."""
103 self.disconnected.connect(self.handle_disconnected)
94 self.connected_d.callback(None)104 self.connected_d.callback(None)
95 for d in self.buffered_data:105 for d in self.buffered_data:
96 logger.debug("writing remote: %d bytes", len(d))106 logger.debug("writing remote: %d bytes", len(d))
@@ -120,13 +130,29 @@
120 raise ConnectionError(400, "Destination port must be an integer.")130 raise ConnectionError(400, "Destination port must be an integer.")
121131
122 self.readyRead.connect(self.handle_ready_read)132 self.readyRead.connect(self.handle_ready_read)
123 # TODO: handle the following signals in an upcoming branch133 self.error.connect(self.handle_error)
124 #self.error.connect(...)
125 #self.proxyAuthenticationRequired.connect(...)
126 self.connectToHost(host, port)134 self.connectToHost(host, port)
127135
128 return self.connected_d136 return self.connected_d
129137
138 def handle_auth_required(self, proxy, authenticator):
139 """Handle the proxyAuthenticationRequired signal."""
140 self.protocol.proxy_auth_required(proxy, authenticator)
141
142 def handle_error(self, socket_error):
143 """Some error happened while connecting."""
144 error_description = "%s (%d)" % (self.errorString(), socket_error)
145 logger.error("connection error: %s", error_description)
146 if self.connected_d.called:
147 return
148
149 if socket_error == self.ProxyAuthenticationRequiredError:
150 error = ProxyAuthenticationError(407, error_description)
151 else:
152 error = ConnectionError(500, error_description)
153
154 self.connected_d.errback(error)
155
130 def handle_ready_read(self):156 def handle_ready_read(self):
131 """Forward data from the remote end to the parent protocol."""157 """Forward data from the remote end to the parent protocol."""
132 data = self.readAll()158 data = self.readAll()
@@ -149,19 +175,36 @@
149 """Initialize this protocol."""175 """Initialize this protocol."""
150 BaseTunnelProtocol.__init__(self)176 BaseTunnelProtocol.__init__(self)
151 self.hostport = ""177 self.hostport = ""
152 self.client = client_class(self)178 self.client = None
179 self.client_class = client_class
180 self.proxy_credentials = None
181 self.proxy_domain = None
153182
154 def error_response(self, code, description):183 def error_response(self, code, description):
155 """Write a response with an error, and disconnect."""184 """Write a response with an error, and disconnect."""
156 self.write_transport("HTTP/1.0 %d %s" % (code, description) + CRLF * 2)185 self.write_transport("HTTP/1.0 %d %s" % (code, description) + CRLF * 2)
157 self.transport.loseConnection()186 self.transport.loseConnection()
158 self.client.stop()187 if self.client:
188 self.client.stop()
159 self.clearLineBuffer()189 self.clearLineBuffer()
160190
161 def write_transport(self, data):191 def write_transport(self, data):
162 """Write a response in the transport."""192 """Write a response in the transport."""
163 self.transport.write(data)193 self.transport.write(data)
164194
195 def proxy_auth_required(self, proxy, authenticator):
196 """Proxy authentication is required."""
197 logger.info("auth_required %r, %r, %r", self.proxy_credentials,
198 proxy.hostName(), self.proxy_domain)
199 if self.proxy_credentials and proxy.hostName() == self.proxy_domain:
200 logger.info("Credentials added to authenticator: %r.",
201 self.proxy_credentials)
202 authenticator.setUser(self.proxy_credentials["username"])
203 authenticator.setPassword(self.proxy_credentials["password"])
204 else:
205 logger.info("Credentials needed, but none available.")
206 self.proxy_domain = proxy.hostName()
207
165 def handle_first_line(self, line):208 def handle_first_line(self, line):
166 """Special handling for the first line received."""209 """Special handling for the first line received."""
167 try:210 try:
@@ -180,7 +223,24 @@
180 def headers_done(self):223 def headers_done(self):
181 """An empty line was received, start connecting and switch mode."""224 """An empty line was received, start connecting and switch mode."""
182 try:225 try:
183 yield self.client.connect(self.hostport)226 try:
227 logger.info("Connecting once")
228 self.client = self.client_class(self)
229 yield self.client.connect(self.hostport)
230 except ProxyAuthenticationError:
231 if not self.proxy_domain:
232 logger.info("No proxy domain defined")
233 raise
234
235 credentials = yield Keyring().get_credentials(
236 str(self.proxy_domain))
237 if "username" in credentials:
238 self.proxy_credentials = credentials
239 logger.info("Connecting again with keyring credentials")
240 self.client = self.client_class(self)
241 yield self.client.connect(self.hostport)
242 logger.info("Connected with keyring credentials")
243
184 response_headers = {244 response_headers = {
185 "Server": "Ubuntu One proxy tunnel",245 "Server": "Ubuntu One proxy tunnel",
186 }246 }
@@ -188,7 +248,10 @@
188 CRLF + self.format_headers(response_headers) +248 CRLF + self.format_headers(response_headers) +
189 CRLF)249 CRLF)
190 except ConnectionError as e:250 except ConnectionError as e:
251 logger.exception("Connection error")
191 self.error_response(e.code, e.description)252 self.error_response(e.code, e.description)
253 except Exception:
254 logger.exception("Unhandled problem while connecting")
192255
193 def rawDataReceived(self, data):256 def rawDataReceived(self, data):
194 """Tunnel all raw data straight to the other side."""257 """Tunnel all raw data straight to the other side."""
@@ -269,7 +332,7 @@
269 settings = gsettings.get_proxy_settings()332 settings = gsettings.get_proxy_settings()
270 enabled = len(settings) > 0333 enabled = len(settings) > 0
271 if enabled:334 if enabled:
272 proxy = build_proxy(settings["http"])335 proxy = build_proxy(settings)
273 QNetworkProxy.setApplicationProxy(proxy)336 QNetworkProxy.setApplicationProxy(proxy)
274 else:337 else:
275 logger.info("Proxy is disabled.")338 logger.info("Proxy is disabled.")
@@ -277,7 +340,7 @@
277 else:340 else:
278 query = QNetworkProxyQuery(host, port)341 query = QNetworkProxyQuery(host, port)
279 proxies = QNetworkProxyFactory.systemProxyForQuery(query)342 proxies = QNetworkProxyFactory.systemProxyForQuery(query)
280 return len(proxies) and proxies[0].type() != QNetworkProxy.NoProxy343 return len(proxies) and proxies[0].type() != QNetworkProxy.DefaultProxy
281344
282345
283def main(argv):346def main(argv):
@@ -286,6 +349,8 @@
286 sys.stdout.write("Proxy not enabled.")349 sys.stdout.write("Proxy not enabled.")
287 sys.stdout.flush()350 sys.stdout.flush()
288 else:351 else:
352 from dbus.mainloop.qt import DBusQtMainLoop
353 DBusQtMainLoop(set_as_default=True)
289 app = QCoreApplication(argv)354 app = QCoreApplication(argv)
290 tunnel_server = TunnelServer()355 tunnel_server = TunnelServer()
291 sys.stdout.write("%s: %d\n" % (TUNNEL_PORT_LABEL, tunnel_server.port))356 sys.stdout.write("%s: %d\n" % (TUNNEL_PORT_LABEL, tunnel_server.port))

Subscribers

People subscribed via source and target branches