import re, struct, socket, select, subprocess, traceback if not globals().get('skip_imports'): import ssnet, helpers, hostwatch from ssnet import SockWrapper, Handler, Proxy, Mux, MuxWrapper from helpers import * def _ipmatch(ipstr): if ipstr == 'default': ipstr = '0.0.0.0/0' m = re.match(r'^(\d+(\.\d+(\.\d+(\.\d+)?)?)?)(?:/(\d+))?$', ipstr) if m: g = m.groups() ips = g[0] width = int(g[4] or 32) if g[1] == None: ips += '.0.0.0' width = min(width, 8) elif g[2] == None: ips += '.0.0' width = min(width, 16) elif g[3] == None: ips += '.0' width = min(width, 24) return (struct.unpack('!I', socket.inet_aton(ips))[0], width) def _ipstr(ip, width): if width >= 32: return ip else: return "%s/%d" % (ip, width) def _maskbits(netmask): if not netmask: return 32 for i in range(32): if netmask[0] & (1<= 1: helpers.logprefix = ' s: ' else: helpers.logprefix = 'server: ' routes = list(list_routes()) debug1('available routes:\n') for r in routes: debug1(' %s/%d\n' % r) # synchronization header sys.stdout.write('SSHUTTLE0001') sys.stdout.flush() handlers = [] mux = Mux(socket.fromfd(sys.stdin.fileno(), socket.AF_INET, socket.SOCK_STREAM), socket.fromfd(sys.stdout.fileno(), socket.AF_INET, socket.SOCK_STREAM)) handlers.append(mux) routepkt = ''.join('%s,%d\n' % r for r in routes) mux.send(0, ssnet.CMD_ROUTES, routepkt) hw = Hostwatch() def hostwatch_ready(): assert(hw.pid) content = hw.sock.recv(4096) if content: mux.send(0, ssnet.CMD_HOST_LIST, content) else: raise Fatal('hostwatch process died') def got_host_req(data): if not hw.pid: (hw.pid,hw.sock) = start_hostwatch(data.strip().split()) handlers.append(Handler(socks = [hw.sock], callback = hostwatch_ready)) mux.got_host_req = got_host_req def new_channel(channel, data): (dstip,dstport) = data.split(',', 1) dstport = int(dstport) outwrap = ssnet.connect_dst(dstip,dstport) handlers.append(Proxy(MuxWrapper(mux, channel), outwrap)) mux.new_channel = new_channel while mux.ok: if hw.pid: (rpid, rv) = os.waitpid(hw.pid, os.WNOHANG) if rpid: raise Fatal('hostwatch exited unexpectedly: code 0x%04x\n' % rv) r = set() w = set() x = set() handlers = filter(lambda s: s.ok, handlers) for s in handlers: s.pre_select(r,w,x) debug2('Waiting: %d[%d,%d,%d] (fullness=%d/%d)...\n' % (len(handlers), len(r), len(w), len(x), mux.fullness, mux.too_full)) (r,w,x) = select.select(r,w,x) #log('r=%r w=%r x=%r\n' % (r,w,x)) ready = set(r) | set(w) | set(x) for s in handlers: #debug2('check: %r: %r\n' % (s, s.socks & ready)) if s.socks & ready: s.callback() mux.check_fullness() mux.callback()