mirror of
https://github.com/sshuttle/sshuttle.git
synced 2025-01-08 06:59:32 +01:00
PEP8 fixes.
This commit is contained in:
parent
5529a04cc9
commit
f1c79c7e92
@ -1,4 +1,5 @@
|
||||
import sys, zlib
|
||||
import sys
|
||||
import zlib
|
||||
|
||||
z = zlib.decompressobj()
|
||||
mainmod = sys.modules[__name__]
|
||||
|
@ -1,8 +1,17 @@
|
||||
import struct, select, errno, re, signal, time
|
||||
import struct
|
||||
import errno
|
||||
import re
|
||||
import signal
|
||||
import time
|
||||
import compat.ssubprocess as ssubprocess
|
||||
import helpers, ssnet, ssh, ssyslog
|
||||
import helpers
|
||||
import os
|
||||
import ssnet
|
||||
import ssh
|
||||
import ssyslog
|
||||
import sys
|
||||
from ssnet import SockWrapper, Handler, Proxy, Mux, MuxWrapper
|
||||
from helpers import *
|
||||
from helpers import log, debug1, debug2, debug3, Fatal, islocal
|
||||
|
||||
recvmsg = None
|
||||
try:
|
||||
@ -23,6 +32,7 @@ except AttributeError:
|
||||
|
||||
_extra_fd = os.open('/dev/null', os.O_RDONLY)
|
||||
|
||||
|
||||
def got_signal(signum, frame):
|
||||
log('exiting on signal %d\n' % signum)
|
||||
sys.exit(1)
|
||||
@ -40,7 +50,8 @@ IPV6_RECVORIGDSTADDR = IPV6_ORIGDSTADDR
|
||||
if recvmsg == "python":
|
||||
def recv_udp(listener, bufsize):
|
||||
debug3('Accept UDP python using recvmsg.\n')
|
||||
data, ancdata, msg_flags, srcip = listener.recvmsg(4096,socket.CMSG_SPACE(24))
|
||||
data, ancdata, msg_flags, srcip = listener.recvmsg(
|
||||
4096, socket.CMSG_SPACE(24))
|
||||
dstip = None
|
||||
family = None
|
||||
for cmsg_level, cmsg_type, cmsg_data in ancdata:
|
||||
@ -70,7 +81,8 @@ if recvmsg == "python":
|
||||
elif recvmsg == "socket_ext":
|
||||
def recv_udp(listener, bufsize):
|
||||
debug3('Accept UDP using socket_ext recvmsg.\n')
|
||||
srcip, data, adata, flags = listener.recvmsg((bufsize,),socket.CMSG_SPACE(24))
|
||||
srcip, data, adata, flags = listener.recvmsg(
|
||||
(bufsize,), socket.CMSG_SPACE(24))
|
||||
dstip = None
|
||||
family = None
|
||||
for a in adata:
|
||||
@ -82,7 +94,8 @@ elif recvmsg == "socket_ext":
|
||||
length = 4
|
||||
else:
|
||||
raise Fatal("Unsupported socket type '%s'" % family)
|
||||
ip = socket.inet_ntop(family, a.cmsg_data[start:start+length])
|
||||
ip = socket.inet_ntop(
|
||||
family, a.cmsg_data[start:start + length])
|
||||
dstip = (ip, port)
|
||||
break
|
||||
elif a.cmsg_level == SOL_IPV6 and a.cmsg_type == IPV6_ORIGDSTADDR:
|
||||
@ -93,7 +106,8 @@ elif recvmsg == "socket_ext":
|
||||
length = 16
|
||||
else:
|
||||
raise Fatal("Unsupported socket type '%s'" % family)
|
||||
ip = socket.inet_ntop(family, a.cmsg_data[start:start+length])
|
||||
ip = socket.inet_ntop(
|
||||
family, a.cmsg_data[start:start + length])
|
||||
dstip = (ip, port)
|
||||
break
|
||||
return (srcip, dstip, data[0])
|
||||
@ -201,9 +215,15 @@ class MultiListener:
|
||||
|
||||
def add_handler(self, handlers, callback, method, mux):
|
||||
if self.v6:
|
||||
handlers.append(Handler([self.v6], lambda: callback(self.v6, method, mux, handlers)))
|
||||
handlers.append(
|
||||
Handler(
|
||||
[self.v6],
|
||||
lambda: callback(self.v6, method, mux, handlers)))
|
||||
if self.v4:
|
||||
handlers.append(Handler([self.v4], lambda: callback(self.v4, method, mux, handlers)))
|
||||
handlers.append(
|
||||
Handler(
|
||||
[self.v4],
|
||||
lambda: callback(self.v4, method, mux, handlers)))
|
||||
|
||||
def listen(self, backlog):
|
||||
if self.v6:
|
||||
@ -239,7 +259,9 @@ class MultiListener:
|
||||
|
||||
|
||||
class FirewallClient:
|
||||
def __init__(self, port_v6, port_v4, subnets_include, subnets_exclude, dnsport_v6, dnsport_v4, method, udp):
|
||||
|
||||
def __init__(self, port_v6, port_v4, subnets_include, subnets_exclude,
|
||||
dnsport_v6, dnsport_v4, method, udp):
|
||||
self.auto_nets = []
|
||||
self.subnets_include = subnets_include
|
||||
self.subnets_exclude = subnets_exclude
|
||||
@ -261,6 +283,7 @@ class FirewallClient:
|
||||
# Instead, attach a *bidirectional* socket to its stdout, and use
|
||||
# that for talking in both directions.
|
||||
(s1, s2) = socket.socketpair()
|
||||
|
||||
def setup():
|
||||
# run in the child process
|
||||
s2.close()
|
||||
@ -321,6 +344,8 @@ class FirewallClient:
|
||||
|
||||
dnsreqs = {}
|
||||
udp_by_src = {}
|
||||
|
||||
|
||||
def expire_connections(now, mux):
|
||||
for chan, timeout in dnsreqs.items():
|
||||
if timeout < now:
|
||||
@ -355,7 +380,7 @@ def onaccept_tcp(listener, method, mux, handlers):
|
||||
else:
|
||||
raise
|
||||
if method == "tproxy":
|
||||
dstip = sock.getsockname();
|
||||
dstip = sock.getsockname()
|
||||
else:
|
||||
dstip = original_dst(sock)
|
||||
debug1('Accept TCP: %s:%r -> %s:%r.\n' % (srcip[0], srcip[1],
|
||||
@ -369,7 +394,8 @@ def onaccept_tcp(listener, method, mux, handlers):
|
||||
log('warning: too many open channels. Discarded connection.\n')
|
||||
sock.close()
|
||||
return
|
||||
mux.send(chan, ssnet.CMD_TCP_CONNECT, '%d,%s,%s' % (sock.family, dstip[0], dstip[1]))
|
||||
mux.send(chan, ssnet.CMD_TCP_CONNECT, '%d,%s,%s' %
|
||||
(sock.family, dstip[0], dstip[1]))
|
||||
outwrap = MuxWrapper(mux, chan)
|
||||
handlers.append(Proxy(SockWrapper(sock, sock), outwrap))
|
||||
expire_connections(time.time(), mux)
|
||||
@ -395,14 +421,17 @@ def onaccept_udp(listener, method, mux, handlers):
|
||||
now = time.time()
|
||||
srcip, dstip, data = recv_udp(listener, 4096)
|
||||
if not dstip:
|
||||
debug1("-- ignored UDP from %r: couldn't determine destination IP address\n" % (srcip,))
|
||||
debug1(
|
||||
"-- ignored UDP from %r: "
|
||||
"couldn't determine destination IP address\n" % (srcip,))
|
||||
return
|
||||
debug1('Accept UDP: %r -> %r.\n' % (srcip, dstip,))
|
||||
if srcip in udp_by_src:
|
||||
chan, timeout = udp_by_src[srcip]
|
||||
else:
|
||||
chan = mux.next_channel()
|
||||
mux.channels[chan] = lambda cmd,data: udp_done(chan, data, method, listener.family, dstip=srcip)
|
||||
mux.channels[chan] = lambda cmd, data: udp_done(
|
||||
chan, data, method, listener.family, dstip=srcip)
|
||||
mux.send(chan, ssnet.CMD_UDP_OPEN, listener.family)
|
||||
udp_by_src[srcip] = chan, now + 30
|
||||
|
||||
@ -433,17 +462,21 @@ def ondns(listener, method, mux, handlers):
|
||||
now = time.time()
|
||||
srcip, dstip, data = recv_udp(listener, 4096)
|
||||
if method == "tproxy" and not dstip:
|
||||
debug1("-- ignored UDP from %r: couldn't determine destination IP address\n" % (srcip,))
|
||||
debug1(
|
||||
"-- ignored UDP from %r: "
|
||||
"couldn't determine destination IP address\n" % (srcip,))
|
||||
return
|
||||
debug1('DNS request from %r to %r: %d bytes\n' % (srcip, dstip, len(data)))
|
||||
chan = mux.next_channel()
|
||||
dnsreqs[chan] = now + 30
|
||||
mux.send(chan, ssnet.CMD_DNS_REQ, data)
|
||||
mux.channels[chan] = lambda cmd,data: dns_done(chan, data, method, listener, srcip=dstip, dstip=srcip, mux=mux)
|
||||
mux.channels[chan] = lambda cmd, data: dns_done(
|
||||
chan, data, method, listener, srcip=dstip, dstip=srcip, mux=mux)
|
||||
expire_connections(now, mux)
|
||||
|
||||
|
||||
def _main(tcp_listener, udp_listener, fw, ssh_cmd, remotename, python, latency_control,
|
||||
def _main(tcp_listener, udp_listener, fw, ssh_cmd, remotename,
|
||||
python, latency_control,
|
||||
dns_listener, method, seed_hosts, auto_nets,
|
||||
syslog, daemon):
|
||||
handlers = []
|
||||
@ -454,7 +487,8 @@ def _main(tcp_listener, udp_listener, fw, ssh_cmd, remotename, python, latency_c
|
||||
debug1('connecting to server...\n')
|
||||
|
||||
try:
|
||||
(serverproc, serversock) = ssh.connect(ssh_cmd, remotename, python,
|
||||
(serverproc, serversock) = ssh.connect(
|
||||
ssh_cmd, remotename, python,
|
||||
stderr=ssyslog._p and ssyslog._p.stdin,
|
||||
options=dict(latency_control=latency_control, method=method))
|
||||
except socket.error, e:
|
||||
@ -531,7 +565,7 @@ def _main(tcp_listener, udp_listener, fw, ssh_cmd, remotename, python, latency_c
|
||||
if dns_listener:
|
||||
dns_listener.add_handler(handlers, ondns, method, mux)
|
||||
|
||||
if seed_hosts != None:
|
||||
if seed_hosts is not None:
|
||||
debug1('seed_hosts: %r\n' % seed_hosts)
|
||||
mux.send(0, ssnet.CMD_HOST_REQ, '\n'.join(seed_hosts))
|
||||
|
||||
@ -684,20 +718,23 @@ def main(listenip_v6, listenip_v4,
|
||||
dnsport_v4 = 0
|
||||
dns_listener = None
|
||||
|
||||
fw = FirewallClient(redirectport_v6, redirectport_v4, subnets_include, subnets_exclude, dnsport_v6, dnsport_v4, method, udp)
|
||||
fw = FirewallClient(redirectport_v6, redirectport_v4, subnets_include,
|
||||
subnets_exclude, dnsport_v6, dnsport_v4, method, udp)
|
||||
|
||||
if fw.method == "tproxy":
|
||||
tcp_listener.setsockopt(socket.SOL_IP, IP_TRANSPARENT, 1)
|
||||
if udp_listener:
|
||||
udp_listener.setsockopt(socket.SOL_IP, IP_TRANSPARENT, 1)
|
||||
if udp_listener.v4 is not None:
|
||||
udp_listener.v4.setsockopt(socket.SOL_IP, IP_RECVORIGDSTADDR, 1)
|
||||
udp_listener.v4.setsockopt(
|
||||
socket.SOL_IP, IP_RECVORIGDSTADDR, 1)
|
||||
if udp_listener.v6 is not None:
|
||||
udp_listener.v6.setsockopt(SOL_IPV6, IPV6_RECVORIGDSTADDR, 1)
|
||||
if dns_listener:
|
||||
dns_listener.setsockopt(socket.SOL_IP, IP_TRANSPARENT, 1)
|
||||
if dns_listener.v4 is not None:
|
||||
dns_listener.v4.setsockopt(socket.SOL_IP, IP_RECVORIGDSTADDR, 1)
|
||||
dns_listener.v4.setsockopt(
|
||||
socket.SOL_IP, IP_RECVORIGDSTADDR, 1)
|
||||
if dns_listener.v6 is not None:
|
||||
dns_listener.v6.setsockopt(SOL_IPV6, IPV6_RECVORIGDSTADDR, 1)
|
||||
|
||||
|
@ -1,7 +1,13 @@
|
||||
import re, errno, socket, select, struct
|
||||
import errno
|
||||
import socket
|
||||
import select
|
||||
import struct
|
||||
import compat.ssubprocess as ssubprocess
|
||||
import helpers, ssyslog
|
||||
from helpers import *
|
||||
import ssyslog
|
||||
import sys
|
||||
import os
|
||||
from helpers import log, debug1, debug3, islocal, Fatal, family_to_string, \
|
||||
resolvconf_nameservers
|
||||
|
||||
# python doesn't have a definition for this
|
||||
IPPROTO_DIVERT = 254
|
||||
@ -45,6 +51,8 @@ def _ipt(family, table, *args):
|
||||
|
||||
|
||||
_no_ttl_module = False
|
||||
|
||||
|
||||
def _ipt_ttl(family, *args):
|
||||
global _no_ttl_module
|
||||
if not _no_ttl_module:
|
||||
@ -72,13 +80,17 @@ def _ipt_ttl(family, *args):
|
||||
def do_iptables_nat(port, dnsport, family, subnets, udp):
|
||||
# only ipv4 supported with NAT
|
||||
if family != socket.AF_INET:
|
||||
raise Exception('Address family "%s" unsupported by nat method'%family_to_string(family))
|
||||
raise Exception(
|
||||
'Address family "%s" unsupported by nat method'
|
||||
% family_to_string(family))
|
||||
if udp:
|
||||
raise Exception("UDP not supported by nat method")
|
||||
|
||||
table = "nat"
|
||||
|
||||
def ipt(*args):
|
||||
return _ipt(family, table, *args)
|
||||
|
||||
def ipt_ttl(*args):
|
||||
return _ipt_ttl(family, table, *args)
|
||||
|
||||
@ -103,7 +115,8 @@ def do_iptables_nat(port, dnsport, family, subnets, udp):
|
||||
# to least-specific, and at any given level of specificity, we want
|
||||
# excludes to come first. That's why the columns are in such a non-
|
||||
# intuitive order.
|
||||
for f,swidth,sexclude,snet in sorted(subnets, key=lambda s: s[1], reverse=True):
|
||||
for f, swidth, sexclude, snet \
|
||||
in sorted(subnets, key=lambda s: s[1], reverse=True):
|
||||
if sexclude:
|
||||
ipt('-A', chain, '-j', 'RETURN',
|
||||
'--dest', '%s/%s' % (snet, swidth),
|
||||
@ -126,11 +139,15 @@ def do_iptables_nat(port, dnsport, family, subnets, udp):
|
||||
|
||||
def do_iptables_tproxy(port, dnsport, family, subnets, udp):
|
||||
if family not in [socket.AF_INET, socket.AF_INET6]:
|
||||
raise Exception('Address family "%s" unsupported by tproxy method'%family_to_string(family))
|
||||
raise Exception(
|
||||
'Address family "%s" unsupported by tproxy method'
|
||||
% family_to_string(family))
|
||||
|
||||
table = "mangle"
|
||||
|
||||
def ipt(*args):
|
||||
return _ipt(family, table, *args)
|
||||
|
||||
def ipt_ttl(*args):
|
||||
return _ipt_ttl(family, table, *args)
|
||||
|
||||
@ -182,7 +199,8 @@ def do_iptables_tproxy(port, dnsport, family, subnets, udp):
|
||||
'--on-port', str(dnsport))
|
||||
|
||||
if subnets:
|
||||
for f,swidth,sexclude,snet in sorted(subnets, key=lambda s: s[1], reverse=True):
|
||||
for f, swidth, sexclude, snet \
|
||||
in sorted(subnets, key=lambda s: s[1], reverse=True):
|
||||
if sexclude:
|
||||
ipt('-A', mark_chain, '-j', 'RETURN',
|
||||
'--dest', '%s/%s' % (snet, swidth),
|
||||
@ -191,10 +209,12 @@ def do_iptables_tproxy(port, dnsport, family, subnets, udp):
|
||||
'--dest', '%s/%s' % (snet, swidth),
|
||||
'-m', 'tcp', '-p', 'tcp')
|
||||
else:
|
||||
ipt('-A', mark_chain, '-j', 'MARK', '--set-mark', '1',
|
||||
ipt('-A', mark_chain, '-j', 'MARK',
|
||||
'--set-mark', '1',
|
||||
'--dest', '%s/%s' % (snet, swidth),
|
||||
'-m', 'tcp', '-p', 'tcp')
|
||||
ipt('-A', tproxy_chain, '-j', 'TPROXY', '--tproxy-mark', '0x1/0x1',
|
||||
ipt('-A', tproxy_chain, '-j', 'TPROXY',
|
||||
'--tproxy-mark', '0x1/0x1',
|
||||
'--dest', '%s/%s' % (snet, swidth),
|
||||
'-m', 'tcp', '-p', 'tcp',
|
||||
'--on-port', str(port))
|
||||
@ -207,10 +227,12 @@ def do_iptables_tproxy(port, dnsport, family, subnets, udp):
|
||||
'--dest', '%s/%s' % (snet, swidth),
|
||||
'-m', 'udp', '-p', 'udp')
|
||||
elif udp:
|
||||
ipt('-A', mark_chain, '-j', 'MARK', '--set-mark', '1',
|
||||
ipt('-A', mark_chain, '-j', 'MARK',
|
||||
'--set-mark', '1',
|
||||
'--dest', '%s/%s' % (snet, swidth),
|
||||
'-m', 'udp', '-p', 'udp')
|
||||
ipt('-A', tproxy_chain, '-j', 'TPROXY', '--tproxy-mark', '0x1/0x1',
|
||||
ipt('-A', tproxy_chain, '-j', 'TPROXY',
|
||||
'--tproxy-mark', '0x1/0x1',
|
||||
'--dest', '%s/%s' % (snet, swidth),
|
||||
'-m', 'udp', '-p', 'udp',
|
||||
'--on-port', str(port))
|
||||
@ -235,6 +257,8 @@ def ipfw_rule_exists(n):
|
||||
|
||||
|
||||
_oldctls = {}
|
||||
|
||||
|
||||
def _fill_oldctls(prefix):
|
||||
argv = ['sysctl', prefix]
|
||||
p = ssubprocess.Popen(argv, stdout=ssubprocess.PIPE)
|
||||
@ -256,6 +280,8 @@ def _sysctl_set(name, val):
|
||||
|
||||
|
||||
_changedctls = []
|
||||
|
||||
|
||||
def sysctl_set(name, val, permanent=False):
|
||||
PREFIX = 'net.inet.ip'
|
||||
assert(name.startswith(PREFIX + '.'))
|
||||
@ -293,6 +319,8 @@ def _udp_repack(p, src, dst):
|
||||
|
||||
|
||||
_real_dns_server = [None]
|
||||
|
||||
|
||||
def _handle_diversion(divertsock, dnsport):
|
||||
p, tag = divertsock.recvfrom(4096)
|
||||
src, dst = _udp_unpack(p)
|
||||
@ -324,7 +352,9 @@ def ipfw(*args):
|
||||
def do_ipfw(port, dnsport, family, subnets, udp):
|
||||
# IPv6 not supported
|
||||
if family not in [socket.AF_INET, ]:
|
||||
raise Exception('Address family "%s" unsupported by ipfw method'%family_to_string(family))
|
||||
raise Exception(
|
||||
'Address family "%s" unsupported by ipfw method'
|
||||
% family_to_string(family))
|
||||
if udp:
|
||||
raise Exception("UDP not supported by ipfw method")
|
||||
|
||||
@ -360,7 +390,8 @@ def do_ipfw(port, dnsport, family, subnets, udp):
|
||||
|
||||
if subnets:
|
||||
# create new subnet entries
|
||||
for f,swidth,sexclude,snet in sorted(subnets, key=lambda s: s[1], reverse=True):
|
||||
for f, swidth, sexclude, snet \
|
||||
in sorted(subnets, key=lambda s: s[1], reverse=True):
|
||||
if sexclude:
|
||||
ipfw('add', sport, 'skipto', xsport,
|
||||
'log', 'tcp',
|
||||
@ -440,6 +471,8 @@ def program_exists(name):
|
||||
|
||||
|
||||
hostmap = {}
|
||||
|
||||
|
||||
def rewrite_etc_hosts(port):
|
||||
HOSTSFILE = '/etc/hosts'
|
||||
BAKFILE = '%s.sbak' % HOSTSFILE
|
||||
@ -564,13 +597,15 @@ def main(port_v6, port_v4, dnsport_v6, dnsport_v4, method, udp, syslog):
|
||||
|
||||
subnets_v6 = filter(lambda i: i[0] == socket.AF_INET6, subnets)
|
||||
if port_v6:
|
||||
do_wait = do_it(port_v6, dnsport_v6, socket.AF_INET6, subnets_v6, udp)
|
||||
do_wait = do_it(
|
||||
port_v6, dnsport_v6, socket.AF_INET6, subnets_v6, udp)
|
||||
elif len(subnets_v6) > 0:
|
||||
debug1("IPv6 subnets defined but IPv6 disabled\n")
|
||||
|
||||
subnets_v4 = filter(lambda i: i[0] == socket.AF_INET, subnets)
|
||||
if port_v4:
|
||||
do_wait = do_it(port_v4, dnsport_v4, socket.AF_INET, subnets_v4, udp)
|
||||
do_wait = do_it(
|
||||
port_v4, dnsport_v4, socket.AF_INET, subnets_v4, udp)
|
||||
elif len(subnets_v4) > 0:
|
||||
debug1('IPv4 subnets defined but IPv4 disabled\n')
|
||||
|
||||
@ -587,7 +622,8 @@ def main(port_v6, port_v4, dnsport_v6, dnsport_v4, method, udp, syslog):
|
||||
# to stay running so that we don't need a *second* password
|
||||
# authentication at shutdown time - that cleanup is important!
|
||||
while 1:
|
||||
if do_wait: do_wait()
|
||||
if do_wait:
|
||||
do_wait()
|
||||
line = sys.stdin.readline(128)
|
||||
if line.startswith('HOST '):
|
||||
(name, ip) = line[5:].strip().split(',', 1)
|
||||
|
@ -1,8 +1,11 @@
|
||||
import sys, os, socket, errno
|
||||
import sys
|
||||
import socket
|
||||
import errno
|
||||
|
||||
logprefix = ''
|
||||
verbose = 0
|
||||
|
||||
|
||||
def log(s):
|
||||
try:
|
||||
sys.stdout.flush()
|
||||
@ -13,14 +16,17 @@ def log(s):
|
||||
# our tty closes. That sucks, but it's no reason to abort the program.
|
||||
pass
|
||||
|
||||
|
||||
def debug1(s):
|
||||
if verbose >= 1:
|
||||
log(s)
|
||||
|
||||
|
||||
def debug2(s):
|
||||
if verbose >= 2:
|
||||
log(s)
|
||||
|
||||
|
||||
def debug3(s):
|
||||
if verbose >= 3:
|
||||
log(s)
|
||||
@ -83,4 +89,3 @@ def family_to_string(family):
|
||||
return "AF_INET"
|
||||
else:
|
||||
return str(family)
|
||||
|
||||
|
@ -1,8 +1,14 @@
|
||||
import time, socket, re, select, errno
|
||||
import time
|
||||
import socket
|
||||
import re
|
||||
import select
|
||||
import errno
|
||||
import os
|
||||
import sys
|
||||
if not globals().get('skip_imports'):
|
||||
import compat.ssubprocess as ssubprocess
|
||||
import helpers
|
||||
from helpers import *
|
||||
from helpers import log, debug1, debug2, debug3
|
||||
|
||||
POLL_TIME = 60 * 15
|
||||
NETSTAT_POLL_TIME = 30
|
||||
@ -94,7 +100,7 @@ def _check_revdns(ip):
|
||||
debug3('< %s\n' % r[0])
|
||||
check_host(r[0])
|
||||
found_host(r[0], ip)
|
||||
except socket.herror, e:
|
||||
except socket.herror:
|
||||
pass
|
||||
|
||||
|
||||
@ -105,7 +111,7 @@ def _check_dns(hostname):
|
||||
debug3('< %s\n' % ip)
|
||||
check_host(ip)
|
||||
found_host(hostname, ip)
|
||||
except socket.gaierror, e:
|
||||
except socket.gaierror:
|
||||
pass
|
||||
|
||||
|
||||
@ -229,7 +235,7 @@ def check_workgroup(hostname):
|
||||
|
||||
def _enqueue(op, *args):
|
||||
t = (op, args)
|
||||
if queue.get(t) == None:
|
||||
if queue.get(t) is None:
|
||||
queue[t] = 0
|
||||
|
||||
|
||||
|
22
src/main.py
22
src/main.py
@ -1,7 +1,13 @@
|
||||
import sys, os, re, socket
|
||||
import helpers, options, client, server, firewall, hostwatch
|
||||
import compat.ssubprocess as ssubprocess
|
||||
from helpers import *
|
||||
import sys
|
||||
import re
|
||||
import socket
|
||||
import helpers
|
||||
import options
|
||||
import client
|
||||
import server
|
||||
import firewall
|
||||
import hostwatch
|
||||
from helpers import log, Fatal
|
||||
|
||||
|
||||
# 1.2.3.4/5 or just 1.2.3.4
|
||||
@ -11,7 +17,7 @@ def parse_subnet4(s):
|
||||
raise Fatal('%r is not a valid IP subnet format' % s)
|
||||
(a, b, c, d, width) = m.groups()
|
||||
(a, b, c, d) = (int(a or 0), int(b or 0), int(c or 0), int(d or 0))
|
||||
if width == None:
|
||||
if width is None:
|
||||
width = 32
|
||||
else:
|
||||
width = int(width)
|
||||
@ -28,7 +34,7 @@ def parse_subnet6(s):
|
||||
if not m:
|
||||
raise Fatal('%r is not a valid IP subnet format' % s)
|
||||
(net, width) = m.groups()
|
||||
if width == None:
|
||||
if width is None:
|
||||
width = 128
|
||||
else:
|
||||
width = int(width)
|
||||
@ -41,7 +47,7 @@ def parse_subnet6(s):
|
||||
def parse_subnet_file(s):
|
||||
try:
|
||||
handle = open(s, 'r')
|
||||
except OSError, e:
|
||||
except OSError:
|
||||
raise Fatal('Unable to open subnet file: %s' % s)
|
||||
|
||||
raw_config_lines = handle.readlines()
|
||||
@ -84,7 +90,7 @@ def parse_ipport4(s):
|
||||
raise Fatal('%d.%d.%d.%d has numbers > 255' % (a, b, c, d))
|
||||
if port > 65535:
|
||||
raise Fatal('*:%d is greater than the maximum of 65535' % port)
|
||||
if a == None:
|
||||
if a is None:
|
||||
a = b = c = d = 0
|
||||
return ('%d.%d.%d.%d' % (a, b, c, d), port)
|
||||
|
||||
|
@ -1,9 +1,16 @@
|
||||
"""Command-line options parser.
|
||||
With the help of an options spec string, easily parse command-line options.
|
||||
"""
|
||||
import sys, os, textwrap, getopt, re, struct
|
||||
import sys
|
||||
import os
|
||||
import textwrap
|
||||
import getopt
|
||||
import re
|
||||
import struct
|
||||
|
||||
|
||||
class OptDict:
|
||||
|
||||
def __init__(self):
|
||||
self._opts = {}
|
||||
|
||||
@ -48,6 +55,7 @@ def _remove_negative_kv(k, v):
|
||||
return k[3:], not v
|
||||
return k, v
|
||||
|
||||
|
||||
def _remove_negative_k(k):
|
||||
return _remove_negative_kv(k, None)[0]
|
||||
|
||||
@ -55,7 +63,8 @@ def _remove_negative_k(k):
|
||||
def _tty_width():
|
||||
s = struct.pack("HHHH", 0, 0, 0, 0)
|
||||
try:
|
||||
import fcntl, termios
|
||||
import fcntl
|
||||
import termios
|
||||
s = fcntl.ioctl(sys.stderr.fileno(), termios.TIOCGWINSZ, s)
|
||||
except (IOError, ImportError):
|
||||
return _atoi(os.environ.get('WIDTH')) or 70
|
||||
@ -64,6 +73,7 @@ def _tty_width():
|
||||
|
||||
|
||||
class Options:
|
||||
|
||||
"""Option parser.
|
||||
When constructed, two strings are mandatory. The first one is the command
|
||||
name showed before error messages. The second one is a string called an
|
||||
@ -76,6 +86,7 @@ class Options:
|
||||
By default, the parser function is getopt.gnu_getopt, and the abort
|
||||
behaviour is to exit the program.
|
||||
"""
|
||||
|
||||
def __init__(self, optspec, optfunc=getopt.gnu_getopt,
|
||||
onabort=_default_onabort):
|
||||
self.optspec = optspec
|
||||
@ -95,7 +106,8 @@ class Options:
|
||||
first_syn = True
|
||||
while lines:
|
||||
l = lines.pop()
|
||||
if l == '--': break
|
||||
if l == '--':
|
||||
break
|
||||
out.append('%s: %s\n' % (first_syn and 'usage' or ' or', l))
|
||||
first_syn = False
|
||||
out.append('\n')
|
||||
@ -170,7 +182,8 @@ class Options:
|
||||
and "extra" is a list of positional arguments.
|
||||
"""
|
||||
try:
|
||||
(flags,extra) = self.optfunc(args, self._shortopts, self._longopts)
|
||||
(flags, extra) = self.optfunc(
|
||||
args, self._shortopts, self._longopts)
|
||||
except getopt.GetoptError, e:
|
||||
self.fatal(e)
|
||||
|
||||
|
@ -1,9 +1,22 @@
|
||||
import re, struct, socket, select, traceback, time
|
||||
import re
|
||||
import struct
|
||||
import socket
|
||||
import traceback
|
||||
import time
|
||||
import sys
|
||||
import os
|
||||
if not globals().get('skip_imports'):
|
||||
import ssnet, helpers, hostwatch
|
||||
import ssnet
|
||||
import helpers
|
||||
import hostwatch
|
||||
import compat.ssubprocess as ssubprocess
|
||||
from ssnet import SockWrapper, Handler, Proxy, Mux, MuxWrapper
|
||||
from helpers import *
|
||||
from ssnet import Handler, Proxy, Mux, MuxWrapper
|
||||
from helpers import log, debug1, debug2, debug3, Fatal, \
|
||||
resolvconf_random_nameserver
|
||||
|
||||
|
||||
if not globals().get('latency_control'):
|
||||
latency_control = None
|
||||
|
||||
|
||||
def _ipmatch(ipstr):
|
||||
@ -14,13 +27,13 @@ def _ipmatch(ipstr):
|
||||
g = m.groups()
|
||||
ips = g[0]
|
||||
width = int(g[4] or 32)
|
||||
if g[1] == None:
|
||||
if g[1] is None:
|
||||
ips += '.0.0.0'
|
||||
width = min(width, 8)
|
||||
elif g[2] == None:
|
||||
elif g[2] is None:
|
||||
ips += '.0.0'
|
||||
width = min(width, 16)
|
||||
elif g[3] == None:
|
||||
elif g[3] is None:
|
||||
ips += '.0'
|
||||
width = min(width, 24)
|
||||
return (struct.unpack('!I', socket.inet_aton(ips))[0], width)
|
||||
@ -59,7 +72,8 @@ def _list_routes():
|
||||
mask = _maskbits(maskw) # returns 32 if maskw is null
|
||||
width = min(ipw[1], mask)
|
||||
ip = ipw[0] & _shl(_shl(1, width) - 1, 32 - width)
|
||||
routes.append((socket.AF_INET, socket.inet_ntoa(struct.pack('!I', ip)), width))
|
||||
routes.append(
|
||||
(socket.AF_INET, socket.inet_ntoa(struct.pack('!I', ip)), width))
|
||||
rv = p.wait()
|
||||
if rv != 0:
|
||||
log('WARNING: %r returned %d\n' % (argv, rv))
|
||||
@ -91,7 +105,7 @@ def start_hostwatch(seed_hosts):
|
||||
os.dup2(s1.fileno(), 0)
|
||||
s1.close()
|
||||
rv = hostwatch.hw_main(seed_hosts) or 0
|
||||
except Exception, e:
|
||||
except Exception:
|
||||
log('%s\n' % _exc_dump())
|
||||
rv = 98
|
||||
finally:
|
||||
@ -101,12 +115,14 @@ def start_hostwatch(seed_hosts):
|
||||
|
||||
|
||||
class Hostwatch:
|
||||
|
||||
def __init__(self):
|
||||
self.pid = 0
|
||||
self.sock = None
|
||||
|
||||
|
||||
class DnsProxy(Handler):
|
||||
|
||||
def __init__(self, mux, chan, request):
|
||||
# FIXME! IPv4 specific
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
@ -164,6 +180,7 @@ class DnsProxy(Handler):
|
||||
|
||||
|
||||
class UdpProxy(Handler):
|
||||
|
||||
def __init__(self, mux, chan, family):
|
||||
sock = socket.socket(family, socket.SOCK_DGRAM)
|
||||
Handler.__init__(self, [sock])
|
||||
@ -192,11 +209,13 @@ class UdpProxy(Handler):
|
||||
hdr = "%s,%r," % (peer[0], peer[1])
|
||||
self.mux.send(self.chan, ssnet.CMD_UDP_DATA, hdr + data)
|
||||
|
||||
|
||||
def main():
|
||||
if helpers.verbose >= 1:
|
||||
helpers.logprefix = ' s: '
|
||||
else:
|
||||
helpers.logprefix = 'server: '
|
||||
assert latency_control is not None
|
||||
debug1('latency control setting = %r\n' % latency_control)
|
||||
|
||||
routes = list(list_routes())
|
||||
@ -253,6 +272,7 @@ def main():
|
||||
mux.new_channel = new_channel
|
||||
|
||||
dnshandlers = {}
|
||||
|
||||
def dns_req(channel, data):
|
||||
debug2('Incoming DNS request channel=%d.\n' % channel)
|
||||
h = DnsProxy(mux, channel, data)
|
||||
@ -261,6 +281,7 @@ def main():
|
||||
mux.got_dns_req = dns_req
|
||||
|
||||
udphandlers = {}
|
||||
|
||||
def udp_req(channel, cmd, data):
|
||||
debug2('Incoming UDP request channel=%d, cmd=%d\n' % (channel, cmd))
|
||||
if cmd == ssnet.CMD_UDP_DATA:
|
||||
@ -287,13 +308,13 @@ def main():
|
||||
udphandlers[channel] = h
|
||||
mux.got_udp_open = udp_open
|
||||
|
||||
|
||||
while mux.ok:
|
||||
if hw.pid:
|
||||
assert(hw.pid > 0)
|
||||
(rpid, rv) = os.waitpid(hw.pid, os.WNOHANG)
|
||||
if rpid:
|
||||
raise Fatal('hostwatch exited unexpectedly: code 0x%04x\n' % rv)
|
||||
raise Fatal(
|
||||
'hostwatch exited unexpectedly: code 0x%04x\n' % rv)
|
||||
|
||||
ssnet.runonce(handlers, mux)
|
||||
if latency_control:
|
||||
|
15
src/ssh.py
15
src/ssh.py
@ -1,7 +1,11 @@
|
||||
import sys, os, re, socket, zlib
|
||||
import sys
|
||||
import os
|
||||
import re
|
||||
import socket
|
||||
import zlib
|
||||
import compat.ssubprocess as ssubprocess
|
||||
import helpers
|
||||
from helpers import *
|
||||
from helpers import debug2
|
||||
|
||||
|
||||
def readfile(name):
|
||||
@ -24,7 +28,6 @@ def empackage(z, filename, data=None):
|
||||
|
||||
|
||||
def connect(ssh_cmd, rhostport, python, stderr, options):
|
||||
main_exe = sys.argv[0]
|
||||
portl = []
|
||||
|
||||
if (rhostport or '').count(':') > 1:
|
||||
@ -35,7 +38,9 @@ def connect(ssh_cmd, rhostport, python, stderr, options):
|
||||
result[1] = result[1].strip(':')
|
||||
if result[1] is not '':
|
||||
portl = ['-p', str(int(result[1]))]
|
||||
else: # can't disambiguate IPv6 colons and a port number. pass the hostname through.
|
||||
# can't disambiguate IPv6 colons and a port number. pass the hostname
|
||||
# through.
|
||||
else:
|
||||
rhost = rhostport
|
||||
else: # IPv4
|
||||
l = (rhostport or '').split(':', 1)
|
||||
@ -65,7 +70,6 @@ def connect(ssh_cmd, rhostport, python, stderr, options):
|
||||
""" % (helpers.verbose or 0, len(content))
|
||||
pyscript = re.sub(r'\s+', ' ', pyscript.strip())
|
||||
|
||||
|
||||
if not rhost:
|
||||
# ignore the --python argument when running locally; we already know
|
||||
# which python version works.
|
||||
@ -84,6 +88,7 @@ def connect(ssh_cmd, rhostport, python, stderr, options):
|
||||
portl +
|
||||
[rhost, '--', pycmd])
|
||||
(s1, s2) = socket.socketpair()
|
||||
|
||||
def setup():
|
||||
# runs in the child process
|
||||
s2.close()
|
||||
|
21
src/ssnet.py
21
src/ssnet.py
@ -1,6 +1,10 @@
|
||||
import struct, socket, errno, select
|
||||
import struct
|
||||
import socket
|
||||
import errno
|
||||
import select
|
||||
import os
|
||||
if not globals().get('skip_imports'):
|
||||
from helpers import *
|
||||
from helpers import log, debug1, debug2, debug3, Fatal
|
||||
|
||||
MAX_CHANNEL = 65535
|
||||
|
||||
@ -92,7 +96,10 @@ def _try_peername(sock):
|
||||
|
||||
|
||||
_swcount = 0
|
||||
|
||||
|
||||
class SockWrapper:
|
||||
|
||||
def __init__(self, rsock, wsock, connect_to=None, peername=None):
|
||||
global _swcount
|
||||
_swcount += 1
|
||||
@ -243,6 +250,7 @@ class SockWrapper:
|
||||
|
||||
|
||||
class Handler:
|
||||
|
||||
def __init__(self, socks=None, callback=None):
|
||||
self.ok = True
|
||||
self.socks = socks or []
|
||||
@ -265,6 +273,7 @@ class Handler:
|
||||
|
||||
|
||||
class Proxy(Handler):
|
||||
|
||||
def __init__(self, wrap1, wrap2):
|
||||
Handler.__init__(self, [wrap1.rsock, wrap1.wsock,
|
||||
wrap2.rsock, wrap2.wsock])
|
||||
@ -272,8 +281,10 @@ class Proxy(Handler):
|
||||
self.wrap2 = wrap2
|
||||
|
||||
def pre_select(self, r, w, x):
|
||||
if self.wrap1.shut_write: self.wrap2.noread()
|
||||
if self.wrap2.shut_write: self.wrap1.noread()
|
||||
if self.wrap1.shut_write:
|
||||
self.wrap2.noread()
|
||||
if self.wrap2.shut_write:
|
||||
self.wrap1.noread()
|
||||
|
||||
if self.wrap1.connect_to:
|
||||
_add(w, self.wrap1.rsock)
|
||||
@ -312,6 +323,7 @@ class Proxy(Handler):
|
||||
|
||||
|
||||
class Mux(Handler):
|
||||
|
||||
def __init__(self, rsock, wsock):
|
||||
Handler.__init__(self, [rsock, wsock])
|
||||
self.rsock = rsock
|
||||
@ -465,6 +477,7 @@ class Mux(Handler):
|
||||
|
||||
|
||||
class MuxWrapper(SockWrapper):
|
||||
|
||||
def __init__(self, mux, channel):
|
||||
SockWrapper.__init__(self, mux.rsock, mux.wsock)
|
||||
self.mux = mux
|
||||
|
@ -1,8 +1,11 @@
|
||||
import sys, os
|
||||
import sys
|
||||
import os
|
||||
from compat import ssubprocess
|
||||
|
||||
|
||||
_p = None
|
||||
|
||||
|
||||
def start_syslog():
|
||||
global _p
|
||||
_p = ssubprocess.Popen(['logger',
|
||||
|
@ -1,5 +1,8 @@
|
||||
#!/usr/bin/env python
|
||||
import sys, os, socket, select, struct, time
|
||||
import socket
|
||||
import select
|
||||
import struct
|
||||
import time
|
||||
|
||||
listener = socket.socket()
|
||||
listener.bind(('127.0.0.1', 0))
|
||||
|
@ -1,4 +1,6 @@
|
||||
import sys, os, re, subprocess
|
||||
import re
|
||||
import subprocess
|
||||
|
||||
|
||||
def askpass(prompt):
|
||||
prompt = prompt.replace('"', "'")
|
||||
|
@ -1,6 +1,11 @@
|
||||
import sys, os, pty
|
||||
import sys
|
||||
import os
|
||||
import pty
|
||||
from AppKit import *
|
||||
import my, models, askpass
|
||||
import my
|
||||
import models
|
||||
import askpass
|
||||
|
||||
|
||||
def sshuttle_args(host, auto_nets, auto_hosts, dns, nets, debug,
|
||||
no_latency_control):
|
||||
@ -21,21 +26,25 @@ def sshuttle_args(host, auto_nets, auto_hosts, dns, nets, debug,
|
||||
|
||||
|
||||
class _Callback(NSObject):
|
||||
|
||||
def initWithFunc_(self, func):
|
||||
self = super(_Callback, self).init()
|
||||
self.func = func
|
||||
return self
|
||||
|
||||
def func_(self, obj):
|
||||
return self.func(obj)
|
||||
|
||||
|
||||
class Callback:
|
||||
|
||||
def __init__(self, func):
|
||||
self.obj = _Callback.alloc().initWithFunc_(func)
|
||||
self.sel = self.obj.func_
|
||||
|
||||
|
||||
class Runner:
|
||||
|
||||
def __init__(self, argv, logfunc, promptfunc, serverobj):
|
||||
print 'in __init__'
|
||||
self.id = argv
|
||||
@ -65,7 +74,8 @@ class Runner:
|
||||
.initWithFileDescriptor_closeOnDealloc_(fd, True)
|
||||
self.cb = Callback(self.gotdata)
|
||||
NSNotificationCenter.defaultCenter()\
|
||||
.addObserver_selector_name_object_(self.cb.obj, self.cb.sel,
|
||||
.addObserver_selector_name_object_(
|
||||
self.cb.obj, self.cb.sel,
|
||||
NSFileHandleDataAvailableNotification, self.file)
|
||||
self.file.waitForDataInBackgroundAndNotify()
|
||||
|
||||
@ -73,7 +83,7 @@ class Runner:
|
||||
self.wait()
|
||||
|
||||
def _try_wait(self, options):
|
||||
if self.rv == None and self.pid > 0:
|
||||
if self.rv is None and self.pid > 0:
|
||||
pid, code = os.waitpid(self.pid, options)
|
||||
if pid == self.pid:
|
||||
if os.WIFEXITED(code):
|
||||
@ -95,7 +105,7 @@ class Runner:
|
||||
def kill(self):
|
||||
assert(self.pid > 0)
|
||||
print 'killing: pid=%r rv=%r' % (self.pid, self.rv)
|
||||
if self.rv == None:
|
||||
if self.rv is None:
|
||||
self.logfunc('Disconnecting from %s.\n' % self.serverobj.host())
|
||||
os.kill(self.pid, 15)
|
||||
self.wait()
|
||||
@ -122,6 +132,7 @@ class Runner:
|
||||
|
||||
|
||||
class SshuttleApp(NSObject):
|
||||
|
||||
def initialize(self):
|
||||
d = my.PList('UserDefaults')
|
||||
my.Defaults().registerDefaults_(d)
|
||||
@ -145,12 +156,14 @@ class SshuttleController(NSObject):
|
||||
host = server.host()
|
||||
print 'connecting %r' % host
|
||||
self.fill_menu()
|
||||
|
||||
def logfunc(msg):
|
||||
print 'log! (%d bytes)' % len(msg)
|
||||
self.logField.textStorage()\
|
||||
.appendAttributedString_(NSAttributedString.alloc()\
|
||||
.appendAttributedString_(NSAttributedString.alloc()
|
||||
.initWithString_(msg))
|
||||
self.logField.didChangeText()
|
||||
|
||||
def promptfunc(prompt):
|
||||
print 'prompt! %r' % prompt
|
||||
return askpass.askpass(prompt)
|
||||
@ -213,6 +226,7 @@ class SshuttleController(NSObject):
|
||||
it.setRepresentedObject_(obj)
|
||||
it.setTarget_(self)
|
||||
it.setAction_(func)
|
||||
|
||||
def addnote(name):
|
||||
additem(name, None, None)
|
||||
|
||||
@ -271,7 +285,8 @@ class SshuttleController(NSObject):
|
||||
sl = []
|
||||
for s in l:
|
||||
host = s.get('host', None)
|
||||
if not host: continue
|
||||
if not host:
|
||||
continue
|
||||
|
||||
nets = s.get('nets', [])
|
||||
nl = []
|
||||
@ -302,11 +317,13 @@ class SshuttleController(NSObject):
|
||||
l = []
|
||||
for s in self.servers:
|
||||
host = s.host()
|
||||
if not host: continue
|
||||
if not host:
|
||||
continue
|
||||
nets = []
|
||||
for n in s.nets():
|
||||
subnet = n.subnet()
|
||||
if not subnet: continue
|
||||
if not subnet:
|
||||
continue
|
||||
nets.append((subnet, n.width()))
|
||||
d = dict(host=s.host(),
|
||||
nets=nets,
|
||||
|
@ -35,11 +35,14 @@ def _validate_width(v):
|
||||
|
||||
|
||||
class SshuttleNet(NSObject):
|
||||
|
||||
def subnet(self):
|
||||
return getattr(self, '_k_subnet', None)
|
||||
|
||||
def setSubnet_(self, v):
|
||||
self._k_subnet = v
|
||||
config_changed()
|
||||
|
||||
@objc_validator
|
||||
def validateSubnet_error_(self, value, error):
|
||||
# print 'validateSubnet!'
|
||||
@ -47,9 +50,11 @@ class SshuttleNet(NSObject):
|
||||
|
||||
def width(self):
|
||||
return getattr(self, '_k_width', 24)
|
||||
|
||||
def setWidth_(self, v):
|
||||
self._k_width = v
|
||||
config_changed()
|
||||
|
||||
@objc_validator
|
||||
def validateWidth_error_(self, value, error):
|
||||
# print 'validateWidth!'
|
||||
@ -62,7 +67,9 @@ NET_MANUAL = 2
|
||||
LAT_BANDWIDTH = 0
|
||||
LAT_INTERACTIVE = 1
|
||||
|
||||
|
||||
class SshuttleServer(NSObject):
|
||||
|
||||
def init(self):
|
||||
self = super(SshuttleServer, self).init()
|
||||
config_changed()
|
||||
@ -70,22 +77,27 @@ class SshuttleServer(NSObject):
|
||||
|
||||
def wantConnect(self):
|
||||
return getattr(self, '_k_wantconnect', False)
|
||||
|
||||
def setWantConnect_(self, v):
|
||||
self._k_wantconnect = v
|
||||
self.setError_(None)
|
||||
config_changed()
|
||||
if setconnect_callback: setconnect_callback(self)
|
||||
if setconnect_callback:
|
||||
setconnect_callback(self)
|
||||
|
||||
def connected(self):
|
||||
return getattr(self, '_k_connected', False)
|
||||
|
||||
def setConnected_(self, v):
|
||||
print 'setConnected of %r to %r' % (self, v)
|
||||
self._k_connected = v
|
||||
if v: self.setError_(None) # connected ok, so no error
|
||||
if v:
|
||||
self.setError_(None) # connected ok, so no error
|
||||
config_changed()
|
||||
|
||||
def error(self):
|
||||
return getattr(self, '_k_error', None)
|
||||
|
||||
def setError_(self, v):
|
||||
self._k_error = v
|
||||
config_changed()
|
||||
@ -109,16 +121,19 @@ class SshuttleServer(NSObject):
|
||||
n = self.nets()
|
||||
suffix = ' (%d subnet%s)' % (len(n), len(n) != 1 and 's' or '')
|
||||
return self.host() + suffix
|
||||
|
||||
def setTitle_(self, v):
|
||||
# title is always auto-generated
|
||||
config_changed()
|
||||
|
||||
def host(self):
|
||||
return getattr(self, '_k_host', None)
|
||||
|
||||
def setHost_(self, v):
|
||||
self._k_host = v
|
||||
self.setTitle_(None)
|
||||
config_changed()
|
||||
|
||||
@objc_validator
|
||||
def validateHost_error_(self, value, error):
|
||||
# print 'validatehost! %r %r %r' % (self, value, error)
|
||||
@ -128,19 +143,23 @@ class SshuttleServer(NSObject):
|
||||
|
||||
def nets(self):
|
||||
return getattr(self, '_k_nets', [])
|
||||
|
||||
def setNets_(self, v):
|
||||
self._k_nets = v
|
||||
self.setTitle_(None)
|
||||
config_changed()
|
||||
|
||||
def netsHidden(self):
|
||||
# print 'checking netsHidden'
|
||||
return self.autoNets() != NET_MANUAL
|
||||
|
||||
def setNetsHidden_(self, v):
|
||||
config_changed()
|
||||
# print 'setting netsHidden to %r' % v
|
||||
|
||||
def autoNets(self):
|
||||
return getattr(self, '_k_autoNets', NET_AUTO)
|
||||
|
||||
def setAutoNets_(self, v):
|
||||
self._k_autoNets = v
|
||||
self.setNetsHidden_(-1)
|
||||
@ -150,18 +169,21 @@ class SshuttleServer(NSObject):
|
||||
|
||||
def autoHosts(self):
|
||||
return getattr(self, '_k_autoHosts', True)
|
||||
|
||||
def setAutoHosts_(self, v):
|
||||
self._k_autoHosts = v
|
||||
config_changed()
|
||||
|
||||
def useDns(self):
|
||||
return getattr(self, '_k_useDns', False)
|
||||
|
||||
def setUseDns_(self, v):
|
||||
self._k_useDns = v
|
||||
config_changed()
|
||||
|
||||
def latencyControl(self):
|
||||
return getattr(self, '_k_latencyControl', LAT_INTERACTIVE)
|
||||
|
||||
def setLatencyControl_(self, v):
|
||||
self._k_latencyControl = v
|
||||
config_changed()
|
||||
|
@ -1,4 +1,4 @@
|
||||
import sys, os
|
||||
import os
|
||||
from AppKit import *
|
||||
import PyObjCTools.AppHelper
|
||||
|
||||
@ -44,11 +44,13 @@ def Defaults():
|
||||
#
|
||||
def DelayedCallback(func, *args, **kwargs):
|
||||
flag = [0]
|
||||
|
||||
def _go():
|
||||
if flag[0]:
|
||||
print 'running %r (flag=%r)' % (func, flag)
|
||||
flag[0] = 0
|
||||
func(*args, **kwargs)
|
||||
|
||||
def call():
|
||||
flag[0] += 1
|
||||
PyObjCTools.AppHelper.callAfter(_go)
|
||||
|
Loading…
Reference in New Issue
Block a user