Esempio n. 1
0
 def __init__(self, logger):
     ConnectBase.__init__(self, logger)
     self.ports = {} # maps interface -> port -> (use_tls, listening Port)
     self.queue = coros.queue()
     self.expected_local_uris = {} # maps local_uri -> Logger instance
     self.expected_remote_paths = {} # maps full_remote_path -> event
     self.new_full_remote_path_notifier = Notifier()
     self.factory = SpawnFactory(self._incoming_handler, MSRPTransport, local_uri=None, logger=self.logger)
Esempio n. 2
0
    def __init__(self):
        self.participants = []

    def handler(self, conn):
        peer = conn.getPeer()
        print('new connection from %s' % (peer, ))
        conn.write("Welcome! There're %s participants already\n" %
                   (len(self.participants)))
        self.participants.append(conn)
        try:
            for line in conn:
                if line:
                    print('received from %s: %s' % (peer, line))
                    for buddy in self.participants:
                        if buddy is not conn:
                            buddy.sendline('from %s: %s' % (peer, line))
        except Exception as ex:
            print(peer, ex)
        else:
            print(peer, 'connection done')
        finally:
            conn.loseConnection()
            self.participants.remove(conn)


print(__doc__)
chat = Chat()
from twisted.internet import reactor
reactor.listenTCP(8007, SpawnFactory(chat.handler, LineOnlyReceiverTransport))
reactor.run()
    try:
        while True:
            x = source.recv()
            if not x:
                break
            print 'forwarding %s bytes' % len(x)
            dest.write(x)
    finally:
        dest.loseConnection()


def handler(local):
    client = str(local.getHost())
    print 'accepted connection from %s' % client
    remote = GreenClientCreator(reactor, UnbufferedTransport).connectTCP(
        remote_host, remote_port)
    a = proc.spawn(forward, remote, local)
    b = proc.spawn(forward, local, remote)
    proc.waitall([a, b], trap_errors=True)
    print 'closed connection to %s' % client


try:
    local_port, remote_host, remote_port = sys.argv[1:]
except ValueError:
    sys.exit(__doc__)
local_port = int(local_port)
remote_port = int(remote_port)
reactor.listenTCP(local_port, SpawnFactory(handler))
reactor.run()
Esempio n. 4
0
class MSRPServer(ConnectBase):
    """Manage listening sockets. Bind incoming requests.

    MSRPServer solves the problem with AcceptorDirect: concurrent using of 2
    or more AcceptorDirect instances on the same non-zero port is not possible.
    If you initialize() those instances, one after another, one will listen on
    the socket and another will get BindError.

    MSRPServer avoids the problem by sharing the listening socket between multiple connections.
    It has slightly different interface from AcceptorDirect, so it cannot be considered a drop-in
    replacement.
    """

    CLOSE_TIMEOUT = MSRPBindSessionTimeout.seconds * 2

    def __init__(self, logger):
        ConnectBase.__init__(self, logger)
        self.ports = {} # maps interface -> port -> (use_tls, listening Port)
        self.queue = coros.queue()
        self.expected_local_uris = {} # maps local_uri -> Logger instance
        self.expected_remote_paths = {} # maps full_remote_path -> event
        self.new_full_remote_path_notifier = Notifier()
        self.factory = SpawnFactory(self._incoming_handler, MSRPTransport, local_uri=None, logger=self.logger)

    def prepare(self, local_uri=None, logger=None):
        """Start a listening port specified by local_uri if there isn't one on that port/interface already.
        Add `local_uri' to the list of expected URIs, so that incoming connections featuring this URI won't be rejected.
        If `logger' is provided use it for this connection instead of the default one.
        """
        if local_uri is None:
            local_uri = self.generate_local_uri(2855)
        need_listen = True
        if local_uri.port:
            use_tls, listening_port = self.ports.get(local_uri.host, {}).get(local_uri.port, (None, None))
            if listening_port is not None:
                if use_tls==local_uri.use_tls:
                    need_listen = False
                else:
                    listening_port.stopListening()
                    sleep(0) # make the reactor really stop listening, so that the next listen() call won't fail
                    self.ports.pop(local_uri.host, {}).pop(local_uri.port, None)
        else:
            # caller does not care about port number
            for (use_tls, port) in self.ports[local_uri.host]:
                if local_uri.use_tls==use_tls:
                    local_uri.port = port.getHost().port
                    need_listen = False
        if need_listen:
            port = self._listen(local_uri, self.factory)
            self.ports.setdefault(local_uri.host, {})[local_uri.port] = (local_uri.use_tls, port)
        self.expected_local_uris[local_uri] = logger
        return [local_uri]

    def _incoming_handler(self, msrp):
        msg = 'Incoming connection from %s:%s' % (msrp.getPeer().host, msrp.getPeer().port)
        self.logger.info(msg)
        with MSRPBindSessionTimeout.timeout():
            chunk = msrp.read_chunk(10000)
            ToPath = tuple(chunk.headers['To-Path'].decoded)
            if len(ToPath)!=1:
                msrp.write_response(chunk, 400, 'Invalid To-Path', wait=False)
                msrp.loseConnection(wait=False)
                return
            ToPath = ToPath[0]
            if ToPath in self.expected_local_uris:
                logger = self.expected_local_uris.pop(ToPath)
                if logger is not None:
                    msrp.logger = logger
                msrp.local_uri = ToPath
            else:
                msrp.write_response(chunk, 481, 'Unknown To-Path', wait=False)
                msrp.loseConnection(wait=False)
                return
            FromPath = tuple(chunk.headers['From-Path'].decoded)
            # at this point, must wait for complete() function to be called which will
            # provide an event for this full_remote_path
            while True:
                event = self.expected_remote_paths.pop(FromPath, None)
                if event is not None:
                    break
                self.new_full_remote_path_notifier.wait()
        if event is not None:
            msrp._set_full_remote_path(list(FromPath))
            error = msrp.check_incoming_SEND_chunk(chunk)
        else:
            error = MSRPNoSuchSessionError
        if error is None:
            msrp.write_response(chunk, 200, 'OK')
            if 'Content-Type' in chunk.headers or chunk.size>0:
                # chunk must be made available to read_chunk() again because it has payload
                raise NotImplementedError
            if event is not None:
                event.send(msrp)
        else:
            msrp.write_response(chunk, error.code, error.comment)

    def complete(self, full_remote_path):
        """Wait until one of the incoming connections binds using provided full_remote_path.
        Return connected and bound MSRPTransport instance.

        If no such binding was made within MSRPBindSessionTimeout.seconds, raise MSRPBindSessionTimeout.
        """
        full_remote_path = tuple(full_remote_path)
        event = coros.event()
        self.expected_remote_paths[full_remote_path] = event
        try:
            self.new_full_remote_path_notifier.send()
            with MSRPBindSessionTimeout.timeout():
                return event.wait()
        finally:
            self.expected_remote_paths.pop(full_remote_path, None)

    def cleanup(self, local_uri):
        """Remove `local_uri' from the list of expected URIs"""
        self.expected_local_uris.pop(local_uri, None)

    def stopListening(self):
        """Close all the sockets that MSRPServer is listening on"""
        for interface, rest in self.ports.iteritems():
            for port, (use_tls, listening_port) in rest:
                listening_port.stopListening()
        self.ports = {}

    def close(self):
        """Stop listening. Wait for the spawned greenlets to finish"""
        self.stopListening()
        with timeout(self.CLOSE_TIMEOUT, None):
            self.factory.waitall()