stumbling towards transit implementation
This commit is contained in:
		
							parent
							
								
									9dd4c6039f
								
							
						
					
					
						commit
						71e3e73c99
					
				| 
						 | 
					@ -1,5 +1,20 @@
 | 
				
			||||||
import os
 | 
					import os, threading, socket, SocketServer
 | 
				
			||||||
 | 
					from binascii import hexlify
 | 
				
			||||||
from ..util import ipaddrs
 | 
					from ..util import ipaddrs
 | 
				
			||||||
 | 
					from ..util.hkdf import HKDF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
 | 
				
			||||||
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def build_receiver_handshake(key):
 | 
				
			||||||
 | 
					    return "rx\n\n"
 | 
				
			||||||
 | 
					    hexid = HKDF(key, 32, CTXinfo=b"transit_receiver")
 | 
				
			||||||
 | 
					    return "transit receiver %s ready\n\n" % hexlify(hexid)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def build_sender_handshake(key):
 | 
				
			||||||
 | 
					    return "tx\n\n"
 | 
				
			||||||
 | 
					    hexid = HKDF(key, 32, CTXinfo=b"transit_sender")
 | 
				
			||||||
 | 
					    return "transit sender %s ready\n\n" % hexlify(hexid)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TransitSender:
 | 
					class TransitSender:
 | 
				
			||||||
    def __init__(self):
 | 
					    def __init__(self):
 | 
				
			||||||
| 
						 | 
					@ -7,30 +22,153 @@ class TransitSender:
 | 
				
			||||||
    def get_transit_key(self):
 | 
					    def get_transit_key(self):
 | 
				
			||||||
        return self.key
 | 
					        return self.key
 | 
				
			||||||
    def get_direct_hints(self):
 | 
					    def get_direct_hints(self):
 | 
				
			||||||
        pass
 | 
					        return []
 | 
				
			||||||
    def get_relay_hints(self):
 | 
					    def get_relay_hints(self):
 | 
				
			||||||
        return []
 | 
					        return []
 | 
				
			||||||
    def add_receiver_hints(self, hints):
 | 
					    def add_receiver_hints(self, hints):
 | 
				
			||||||
        self.receiver_hints = hints
 | 
					        self.receiver_hints = hints
 | 
				
			||||||
    def establish_connection(self):
 | 
					    def establish_connection(self):
 | 
				
			||||||
        pass
 | 
					        sender_handshake = build_sender_handshake(self.key)
 | 
				
			||||||
 | 
					        receiver_handshake = build_receiver_handshake(self.key)
 | 
				
			||||||
 | 
					        self.connectors = []
 | 
				
			||||||
 | 
					        for hint in self.receiver_hints:
 | 
				
			||||||
 | 
					            connector = _Connector(hint, sender_handshake, receiver_handshake)
 | 
				
			||||||
 | 
					            connector.start()
 | 
				
			||||||
 | 
					            self.connectors.append(connector)
 | 
				
			||||||
    def write(self, data):
 | 
					    def write(self, data):
 | 
				
			||||||
        pass
 | 
					        pass
 | 
				
			||||||
    def close(self):
 | 
					    def close(self):
 | 
				
			||||||
        pass
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class BadHandshake(Exception):
 | 
				
			||||||
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class _Connector(threading.Thread):
 | 
				
			||||||
 | 
					    def __init__(self, owner, hint, send_handshake, expected_handshake):
 | 
				
			||||||
 | 
					        threading.Thread.__init__(self)
 | 
				
			||||||
 | 
					        self.owner = owner
 | 
				
			||||||
 | 
					        self.hint = hint
 | 
				
			||||||
 | 
					        self.send_handshake = send_handshake
 | 
				
			||||||
 | 
					        self.expected_handshake = expected_handshake
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def run(self):
 | 
				
			||||||
 | 
					        addr,port = self.hint.split(",")
 | 
				
			||||||
 | 
					        skt = socket.create_connection((addr,port))
 | 
				
			||||||
 | 
					        print "socket(%s) connected" % self.hint
 | 
				
			||||||
 | 
					        skt.send(self.send_handshake)
 | 
				
			||||||
 | 
					        got = b""
 | 
				
			||||||
 | 
					        while len(got) < len(self.expected_handshake):
 | 
				
			||||||
 | 
					            got += skt.recv(1)
 | 
				
			||||||
 | 
					            if self.expected_handshake[:len(got)] != got:
 | 
				
			||||||
 | 
					                raise BadHandshake("got '%r' want '%r' on %s" %
 | 
				
			||||||
 | 
					                                   (got, self.expected_handshake, self.hint))
 | 
				
			||||||
 | 
					        print "connector ready", self.hint
 | 
				
			||||||
 | 
					        self.owner.connector_connected(skt) # note thread
 | 
				
			||||||
 | 
					        skt.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class MyTCPServer(SocketServer.TCPServer):
 | 
				
			||||||
 | 
					    allow_reuse_address = True
 | 
				
			||||||
 | 
					    def process_request(self, request, client_address):
 | 
				
			||||||
 | 
					        # if the handler returns True, it has given the socket to someone
 | 
				
			||||||
 | 
					        # else, and we should not close it
 | 
				
			||||||
 | 
					        handler = _Handler()
 | 
				
			||||||
 | 
					        t = threading.Thread(target=handler.handle,
 | 
				
			||||||
 | 
					                             args=(SERVER, request, client_address, X))
 | 
				
			||||||
 | 
					        t.daemon = False
 | 
				
			||||||
 | 
					        t.start()
 | 
				
			||||||
 | 
					        self.threads.append(t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            claimed = self.finish_request(request, client_address)
 | 
				
			||||||
 | 
					            if not claimed:
 | 
				
			||||||
 | 
					                self.shutdown_request(request)
 | 
				
			||||||
 | 
					        except:
 | 
				
			||||||
 | 
					            self.handle_error(request, client_address)
 | 
				
			||||||
 | 
					            self.shutdown_request(request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class _Handler:
 | 
				
			||||||
 | 
					    def handle(self, tr, skt, client_address, X):
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            print "handle", skt
 | 
				
			||||||
 | 
					            skt.settimeout(5.0)
 | 
				
			||||||
 | 
					            send_handshake = tr.handler_send_handshake
 | 
				
			||||||
 | 
					            expected_handshake = tr.handler_expected_handshake
 | 
				
			||||||
 | 
					            skt.send(send_handshake)
 | 
				
			||||||
 | 
					            got = b""
 | 
				
			||||||
 | 
					            while len(got) < len(expected_handshake):
 | 
				
			||||||
 | 
					                got += skt.recv(1)
 | 
				
			||||||
 | 
					                if expected_handshake[:len(got)] != got:
 | 
				
			||||||
 | 
					                    raise BadHandshake("got '%r' want '%r'" %
 | 
				
			||||||
 | 
					                                       (got, expected_handshake))
 | 
				
			||||||
 | 
					            print "handler ready", server_address, client_address
 | 
				
			||||||
 | 
					            # give skt to somebody
 | 
				
			||||||
 | 
					            tr.handler_connected(skt) # note thread
 | 
				
			||||||
 | 
					        except:
 | 
				
			||||||
 | 
					            try:
 | 
				
			||||||
 | 
					                skt.shutdown(socket.SHUT_WR)
 | 
				
			||||||
 | 
					            except socket.error:
 | 
				
			||||||
 | 
					                pass
 | 
				
			||||||
 | 
					            skt.close()
 | 
				
			||||||
 | 
					            server.handler_closed()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TransitReceiver:
 | 
					class TransitReceiver:
 | 
				
			||||||
    def __init__(self):
 | 
					    def __init__(self):
 | 
				
			||||||
        pass
 | 
					        self.addrs = ipaddrs.find_addresses()
 | 
				
			||||||
 | 
					        self.my_direct_hints = []
 | 
				
			||||||
 | 
					        self.my_listeners = []
 | 
				
			||||||
 | 
					        for addr in self.addrs:
 | 
				
			||||||
 | 
					            server = MyThreadingTCPServer((addr,9999), _Handler)
 | 
				
			||||||
 | 
					            server.receiver = self
 | 
				
			||||||
 | 
					            ip, port = server.server_address
 | 
				
			||||||
 | 
					            server_thread = threading.Thread(target=server.serve_forever)
 | 
				
			||||||
 | 
					            server_thread.daemon = True
 | 
				
			||||||
 | 
					            server_thread.start()
 | 
				
			||||||
 | 
					            self.my_direct_hints.append("%s,%d" % (addr, port))
 | 
				
			||||||
 | 
					            self.my_listeners.append(server)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def shutdown(self):
 | 
				
			||||||
 | 
					        for server in self.my_listeners:
 | 
				
			||||||
 | 
					            server.shutdown()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_direct_hints(self):
 | 
					    def get_direct_hints(self):
 | 
				
			||||||
        pass
 | 
					        return self.my_direct_hints
 | 
				
			||||||
    def set_transit_key(self, key):
 | 
					    def set_transit_key(self, key):
 | 
				
			||||||
        self.key = key
 | 
					        self.key = key
 | 
				
			||||||
 | 
					        self.handler_send_handshake = build_receiver_handshake(key)
 | 
				
			||||||
 | 
					        self.handler_expected_handshake = build_sender_handshake(key)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def add_sender_direct_hints(self, hints):
 | 
					    def add_sender_direct_hints(self, hints):
 | 
				
			||||||
        self.sender_direct_hints = hints
 | 
					        self.sender_direct_hints = hints # TODO ignored
 | 
				
			||||||
    def add_sender_relay_hints(self, hints):
 | 
					    def add_sender_relay_hints(self, hints):
 | 
				
			||||||
        self.sender_relay_hints = hints
 | 
					        self.sender_relay_hints = hints # TODO ignored
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def connection_resolved(self, x):
 | 
				
			||||||
 | 
					        # get lock
 | 
				
			||||||
 | 
					        # update pending connection list
 | 
				
			||||||
 | 
					        # determine next step
 | 
				
			||||||
 | 
					        # release lock
 | 
				
			||||||
 | 
					        # take next step
 | 
				
			||||||
 | 
					        if good_socket:
 | 
				
			||||||
 | 
					            # cancel listener(s)
 | 
				
			||||||
 | 
					            # cancel handlers (still in negotiation)
 | 
				
			||||||
 | 
					            # cancel connectors (waiting connection or in negotiation)
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
    def establish_connection(self):
 | 
					    def establish_connection(self):
 | 
				
			||||||
        pass
 | 
					        assert self.key
 | 
				
			||||||
 | 
					        # start stuff
 | 
				
			||||||
 | 
					        # wait for a connection to be made
 | 
				
			||||||
 | 
					        self.ready = threading.Event()
 | 
				
			||||||
 | 
					        self.ready.wait()
 | 
				
			||||||
 | 
					        print "connection established"
 | 
				
			||||||
 | 
					        print self.skt
 | 
				
			||||||
 | 
					        return self.skt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def handler_connected(self, skt):
 | 
				
			||||||
 | 
					        self.skt = skt
 | 
				
			||||||
 | 
					        self.ready.set()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def receive(self):
 | 
					    def receive(self):
 | 
				
			||||||
        pass
 | 
					        pass
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user