예제 #1
1
파일: __init__.py 프로젝트: giflw/afn-tools
class Bus(common.AutoClose):
    """
    An Autobus bus. Busses manage a set of published services, and allow
    connecting to other services. A single bus listens on a single TCP
    port and multiplexes all published services over it.
    
    Bus is a subclass of ServiceProvider; the service it provides is a service
    exposing information about what other services, events, functions, and
    objects are present. (This service is more commonly known as the
    introspection service.) You normally won't have to know this; instances of
    Bus register themselves as services with themselves, so you don't need to
    do anything to make the introspection service work.
    """
    def __init__(self, default_discoverers=True, default_publishers=True,
                 port=None):
        """
        Creates a new bus. The bus will listen on the specified port; if none
        is specified (which is the usual case), a port will be chosen from the
        ports not currently in use on this computer.
        
        If default_discoverers is True (the default), a default set of
        discoverers will be installed, and likewise for default_publishers.
        Right now, this simply installs a autobus2.discovery.BroadcastPublisher
        and autobus2.discovery.BroadcastDiscoverer. Others might be added in
        the future.
        """
        # Number of times this bus has been __enter__'d. Allows it to be used
        # as a re-entrant context manager.
        self.context_enters = 0
        if port is None:
            port = 0
        # True once close() has been called
        self.closed = False
        # The TCP server that will listen for connections
        self.server = Socket()
        self.server.bind(("", port))
        # TODO: make the backlog configurable
        self.server.listen(100)
        self.port = self.server.getsockname()[1]
        # Lock that nearly everything bus-related locks on
        self.lock = RLock()
        # PropertyTable whose keys are service ids and whose values are
        # instances of autobus2.local.LocalService
        self.local_services = PropertyTable()
        self.local_services.global_watch(self.local_service_changed)
        # Map of ids of discovered services to DiscoveredService instances
        self.discovered_services = {}
        self.discovery_listeners = []
        # List of (filter, function) tuples, where filter is an info object
        # filter and function is a function to be notified when a matching
        # service is created or deleted
        self.service_listeners = []
        # Set of RemoteConnection instances that have been bound to a service
        self.bound_connections = set()
        # Set of discoverers registered on this bus
        self.discoverers = set()
        # Set of publishers registered on this bus
        self.publishers = set()
        if default_discoverers:
            self.install_discoverer(discovery.BroadcastDiscoverer())
        if default_publishers:
            self.install_publisher(discovery.BroadcastPublisher())
        Thread(name="autobus2.Bus.accept_loop", target=self.accept_loop).start()
        # Disable the introspection service for now. I'm seeing what would
        # happen if I have per-service introspection functions and objects, so
        # I'm disabling the bus-wide introspection service.
        # self._create_introspection_service()
        #
        # Register the bus as a service on itself.
        self.create_service({"type": "autobus.details", "pid": os.getpid()}, _IntrospectionService(self))
    
    def accept_loop(self):
        """
        Called on a new thread to accept socket connections to this bus.
        """
        self.server.settimeout(1)
        while not self.closed:
            try:
                socket = None
                socket = self.server.accept()[0]
                self.setup_inbound_socket(socket)
            except SocketTimeout: # This happens when we time out, which is
                # normal. The 1-second timeout is to fix what appears to be a
                # bug with Windows not properly throwing an exception from
                # accept when another thread closes the socket.
                pass
            except: # This happens when the server socket is closed
                if socket:
                    socket.close() # Make sure it's /really/ closed on the
                    # off chance that something else caused the exception
                if not issubclass(sys.exc_type, SocketError): # Something else
                    # happened
                    print_exc()
                # print "Bus server died"
                return
    
    @synchronized_on("lock")
    def create_service(self, info, provider):
        """
        Creates a new service on this bus. info is the info object to use for
        this service. provider is the instance of
        autobus2.service.ServiceProvider to publish; an instance of
        autobus2.providers.PyServiceProvider can be used to publish a simple
        Python object as a service. (This is how I expect most services to be
        published; writing a custom ServiceProvider subclass should rarely be
        needed.)
        
        The return value is an instance of local.LocalService. You can safely
        ignore it if you don't need it and don't plan on deleting the service
        before you close the bus itself.
        """
        # Create a new id for the service
        service_id = messaging.create_service_id()
        self.set_remote_info_builtins(service_id, info)
        # Create the actual service object
        service = local.LocalService(self, service_id, info, provider)
        # Then store the service in our services map, which will cause the
        # service to be published through the introspection service and through
        # the bus's publishers (see self.local_service_changed).
        self.local_services[service_id] = service
        return service
    
    def _close_service(self, service):
        # This is called from LocalService.close, which will take care of
        # shutting down the service's connections and such. So the only thing
        # we really need to do here is delete the service from the local_service
        # map, which will cause self.local_service_changed to unpublish the
        # service and remove it from the introspection service.
        del self.local_services[service.id]
    
    @synchronized_on("lock")
    def setup_inbound_socket(self, socket):
        # Create a connection and then add it to our list of connections
        connection = local.RemoteConnection(self, socket)
        self.bound_connections.add(connection)
    
    def connect(self, host, port, service_id, timeout=10, open_listener=None,
                close_listener=None, fail_listener=None, lock=None):
        """
        Opens a connection to the specified service on the specified host/port.
        
        The connection will be returned immediately. The actual connection to
        the server will be made as soon as possible in the future. If you need
        to block until the connection actually connects, call wait_for_connect
        on the returned Connection object.
        
        The connection will attempt to reconnect indefinitely whenever it is
        disconnected. If you don't want this behavior, specify a close_listener
        that calls the connection's close method.
        
        Timeout is the TCP timeout to use when connecting. The default is 10;
        this is usually a suitable default. You'll probably only want to
        increase this if you're working on a particularly latent network.
        
        open_listener and close_listener are functions accepting one argument.
        They will be called when the connection successfully connects and when
        the connection disconnects, respectively, and the connection itself
        will be passed in. They are both run synchronously on the connection's
        input thread, so it's guaranteed that, for example, the connection will
        not attempt to reconnect until close_listener has returned. Thus
        close_listener could be set to a function that just closes the
        specified connection in order to effectively disable the auto-reconnect
        feature of connections.
        """
        return remote.Connection(self, host, port, service_id, timeout, open_listener, close_listener, fail_listener, lock)
    
    def connect_to(self, info_filter, timeout=10, open_listener=None, close_listener=None, fail_listener=None, lock=None):
        """
        Locates the first service in the list of discovered services and uses
        self.connect to connect to it. The connection is then returned.
        
        This function will be going away soon. Service proxies (which can be
        obtained using self.get_service_proxy) are the replacement; a single
        service proxy is quite similar to this method, but it can follow the
        service across restarts of the underlying process publishing the
        service, which this method can't.
        """
        with self.lock:
            for service_id, d in self.discovered_services.items():
                if filter_matches(d.info, info_filter):
                    host, port = d.locations.keys()[0]
                    return self.connect(host, port, service_id, timeout, open_listener, close_listener, fail_listener, lock)
            raise exceptions.NoMatchingServiceException()
    
    def get_service_proxy(self, info_filter, bind_function=None, unbind_function=None, multiple=False):
        """
        Returns a service proxy that will connect to services matching the
        specified info object filter. If multiple is False (the default), a
        single service proxy will be returned. If multiple is True, a multiple
        service proxy will be returned. See proxy.SingleServiceProxy and
        proxy.MultipleServiceProxy for the differences between the two.
        
        bind_function and unbind_function are optional functions that will be
        called when the proxy binds to and unbinds from a service,
        respectively. Binding is where a proxy discovers a new service matching
        its info filter and establishes a connection to it. Unbinding is where
        the proxy disconnects from said connection, usually because the service
        went away.
        """
        with self.lock:
            if multiple:
                return proxy.MultipleServiceProxy(self, info_filter, bind_function, unbind_function)
            else:
                return proxy.SingleServiceProxy(self, info_filter)
    
    @synchronized_on("lock")
    def close(self):
        """
        Closes this bus and all services registered on it.
        """
        if self.closed: # Already closed
            return
        self.closed = True
        # First we shut down all of our discoverers
        for discoverer in self.discoverers:
            discoverer.shutdown()
        # Then we need to close all of our services. Closing a service causes
        # self._close_service to be called, which removes the service from the
        # list of services, which causes self.local_service_changed to be
        # called, which unpublishes the service. So we don't need to worry
        # about unpublishing services aside from this.
        for service_id in list(self.local_services):
            self.local_services[service_id].close()
        # Then we shut down all of the publishers
        for publisher in self.publishers:
            publisher.shutdown()
        # Then we shut down the server socket
        net.shutdown(self.server)
        # Then we close all of the connections currently connected to us
        for c in self.bound_connections:
            with no_exceptions:
                c.close()
        # And that's it!
    
    @synchronized_on("lock")
    def install_publisher(self, publisher):
        # Add the publisher to our list and start it up
        self.publishers.add(publisher)
        publisher.startup(self)
        # Then register all of our local services with the publisher
        for service in self.local_services.values():
            publisher.add(service)
    
    @synchronized_on("lock")
    def remove_publisher(self, publisher):
        # Check to make sure that the publisher is already installed
        if publisher not in self.publishers:
            # TODO: Not sure why we're using __builtin__ here...
            raise __builtin__.ValueError("The specified publisher is not currently installed on this bus.")
        # Remove the publisher from our list of publishers
        self.publishers.remove(publisher)
        # Unpublish all of our services from the publisher
        for service in self.local_services.values():
            if service.active:
                publisher.remove(service)
        # Then we shut down the publisher
        publisher.shutdown()
    
    @synchronized_on("lock")
    def install_discoverer(self, discoverer):
        # Add the discoverer to our list of discoverers, then start it up
        self.discoverers.add(discoverer)
        discoverer.startup(self)
    
    @synchronized_on("lock")
    def remove_discoverer(self, discoverer):
        # Check to make sure that the discoverer has already been installed
        if discoverer not in self.discoverers:
            # TODO: Ditto from remove_publisher
            raise __builtin__.ValueError("The specified discoverer is not currently installed on this bus.")
        # Remove the discoverer from our list of discoverers, then shut it
        # down
        self.discoverers.remove(discoverer)
        discoverer.shutdown()
    
    def set_local_info_builtins(self, host, port, service_id, info):
        new_info = info.copy()
        new_info["host"] = host
        new_info["port"] = port
        new_info["service"] = service_id
        return new_info
    
    def set_remote_info_builtins(self, service_id, info):
        """
        Adds some values to the specified info object. The only one added right
        now is hostname, which is the value of socket.gethostname(). I haven't
        really standardized the list of values added here; I hope to at some
        point, though, and have all Autobus client libraries add the same ones.
        """
        info["hostname"] = gethostname()
    
    @synchronized_on("lock")
    def discover(self, discoverer, host, port, service_id, info):
        # print "Discovered:", (host, port, service_id, info)
        # Add the relevant local builtins
        info = self.set_local_info_builtins(host, port, service_id, info)
        # Check to see if the specified service has been discovered yet, and if
        # it hasn't, create an entry for it
        is_new_service = False
        if service_id not in self.discovered_services:
            self.discovered_services[service_id] = DiscoveredService(info)
            is_new_service = True
        discovered_service = self.discovered_services[service_id]
        # Check to see if the specified host/port combination is already
        # present, and if it isn't, add it.
        if (host, port) not in discovered_service.locations:
            discovered_service.locations[(host, port)] = []
        discoverer_list = discovered_service.locations[(host, port)]
        # Check to see if this discoverer has already discovered that host/port
        if discoverer in discoverer_list:
            print ("Warning: discoverer " + str(discoverer) + 
                   " tried to rediscover " + str((host, port, service_id)) +
                   " with info " + str(info))
            return
        # It hasn't, so add it.
        discoverer_list.append(discoverer)
        # The check to see if we need to notify listeners, and do so if we
        # need to
        if is_new_service:
            self.notify_service_listeners(service_id, host, port, info, DISCOVERED) 
    
    @synchronized_on("lock")
    def undiscover(self, discoverer, host, port, service_id):
        # print "Undiscovered:", (host, port, service_id)
        # Check to see if the specified service has been discovered.
        if service_id not in self.discovered_services:
            print ("Warning: discoverer " + str(discoverer) + " tried to "
                   "undiscover " + str((host, port, service_id)) + " when "
                   "such a service does not exist.")
            return
        discovered_service = self.discovered_services[service_id]
        if (host, port) not in discovered_service.locations:
            print ("Warning: discoverer " + str(discoverer) + " tried to "
                   "undiscover " + str((host, port, service_id)) + " when "
                   "that host/port has not yet been discovered.")
            return
        discoverer_list = discovered_service.locations[(host, port)]
        if discoverer not in discoverer_list:
            print ("Warning: discoverer " + str(discoverer) + " tried to "
                   "undiscover " + str((host, port, service_id)) + " when "
                   "this discoverer hasn't discovered that host/port yet.")
            return
        discoverer_list.remove(discoverer)
        if not discoverer_list:
            if discovered_service.locations.keys()[0] == (host, port): # We're
                # removing the first (and therefore default) location, so if
                # there's another location, we need to let the service
                # listeners know that there's a new default location
                if len(discovered_service.locations) > 1: # There will be
                    # another location even after we delete this one
                    new_host, new_port = discovered_service.locations.keys()[1]
                    if not self.closed: # Don't issue changes if we're shutting down
                        self.notify_service_listeners(service_id, new_host, new_port, discovered_service.info, CHANGED)
            del discovered_service.locations[(host, port)]
            if not discovered_service.locations: # That was the last location
                # available for this service, so we delete the service itself,
                # and notify listeners that it was deleted
                del self.discovered_services[service_id]
                self.notify_service_listeners(service_id, host, port, discovered_service.info, UNDISCOVERED)
    
    @synchronized_on("lock")
    def add_service_listener(self, listener, info_filter=None, initial=False):
        """
        Listens for changes in services that are available. listener is a
        function listener(service_id, host, port, info, event) which will be
        called whenever a service becomes available, a service disappears, or
        the host/port that should be used to access a particular service
        changes. service_id is the id of the service; host/port is the host/port
        at which the service can be found, info is the service's info object,
        and event is one of DISCOVERED, UNDISCOVERED, or CHANGED.
        
        If info_filter is a dictionary, only services with info objects matching
        that particular filter (as per the filter_matches function) will cause
        the listener to be called. If info_filter is None (the default), or the
        empty dictionary (since all info objects match the empty dictionary),
        the listener will be called for all services.
        
        If initial is True, the listener will be immediately (and synchronously)
        called once for each service that already exists, passing in DISCOVERED
        as the event. Otherwise, the listener will only be called once the next
        
        """
        # Add the listener to our list of listeners
        self.service_listeners.append((info_filter, listener))
        # Check to see if we're supposed to notify the listener about all
        # matching services that already exist
        if initial:
            # Scan all of the services
            for service_id, discovered_service in self.discovered_services.items():
                if filter_matches(discovered_service.info, info_filter):
                    # If this service matches, notify the listener about it
                    host, port = discovered_service.locations.keys()[0]
                    with print_exceptions:
                        listener(service_id, host, port, discovered_service.info, DISCOVERED)
    
    @synchronized_on("lock")
    def remove_service_listener(self, listener, initial=False):
        # Scan the list of listeners and remove this one. Inefficient, it's
        # true, and I hope to make it more efficient later on.
        for index, (info_filter, l) in enumerate(self.service_listeners[:]):
            # See if we've hit the right listener
            if l == listener:
                # If we have, remove the listener
                del self.service_listeners[index]
                if initial:
                    # Scan through the list of services
                    for service_id, discovered_service in self.discovered_services.items():
                        if filter_matches(discovered_service.info, info_filter):
                            # This service matched, so we notify this
                            # listener that the service was removed
                            with print_exceptions:
                                listener(service_id, None, None, None, UNDISCOVERED)
                # We've found our listener and deleted it, so we return now
                return
    
    def notify_service_listeners(self, service_id, host, port, info, event):
        for filter, listener in self.service_listeners:
            if filter_matches(info, filter):
                with print_exceptions:
                    listener(service_id, host, port, info, event)
    
    def local_service_changed(self, service_id, old, new):
        """
        Called (by the local_services property table) when services come and go.
        All we really need to do is publish/unpublish the service.
        """
        if old:
            for publisher in self.publishers:
                publisher.remove(old)
        if new:
            for publisher in self.publishers:
                publisher.add(new)
예제 #2
0
def tcp_connect_handler(sock: socket.socket, remote: list,
                        server: socketserver.TCPServer):
    global dns_cache

    now = time.strftime("%Y-%m-%d %H:%M:%S")
    remote_addr = remote[0]

    if resolve_dns:
        if remote_addr not in dns_cache:
            remote_addr_info = []
            try:
                remote_addr_info = socket.gethostbyaddr(remote_addr)
            except socket.herror:
                pass
            except:
                msg = "\n%s\n%s\n" % (sys.exc_info()[0], sys.exc_info()[1])
                print(msg)

            if len(remote_addr_info) >= 1:
                remote_addr = remote_addr_info[0]
                dns_cache[remote[0]] = remote_addr
        else:
            remote_addr = dns_cache[remote_addr]

    print("[%s] Incoming connection on %s:%s from %s:%s" %
          (now, sock.getsockname()[0], sock.getsockname()[1], remote_addr,
           remote[1]))

    if fp_tcp_listen:
        fp_tcp_listen.write("%s,%s:%s,%s:%s\n" %
                            (now, sock.getsockname()[0], sock.getsockname()[1],
                             remote_addr, remote[1]))
        fp_tcp_listen.flush()
    sock.close()
예제 #3
0
def _recv_message(sock: socket) -> bytes:
    from time import sleep
    _recv_message.recv_locks[sock].acquire()
    _logger.debug(str(sock.getsockname()) + " waiting for recv message length")
    try:
        tries = 0
        while tries < MAX_RETRY:
            content_length_message = sock.recv(CONTENT_LENGTH_MESSAGE_LENGTH).decode().strip()
            _logger.debug(str(sock.getsockname()) + " got message length message: " + content_length_message)
            if content_length_message:
                content_length = int(content_length_message)
                _logger.debug(
                    str(sock.getsockname()) + " waits for receiving a message of length " + str(content_length))
                break
            else:
                tries = tries + 1
                sleep(1)
        else:
            _logger.warning("Did not receive content length message.")
            return b""
    except ConnectionResetError:
        _logger.info("The socket " + str(sock.getsockname()) + " was closed.")
        content_length = 0
    except Exception as ex:
        _logger.warning("The socket stream of " + str(sock.getsockname())
                        + " got corrupted. It is likely that any further message will also break. Cause: " + str(ex))
        content_length = 0
    received_message = b""
    while len(received_message) < content_length:
        received_message = received_message + sock.recv(content_length - len(received_message))
    _recv_message.recv_locks[sock].release()
    return received_message
def transfer(src: socket.socket, dst: socket.socket, send: bool) -> None:
    """
    Send data received on the source socket to the destination socket.
    """
    src_addr, src_port = src.getsockname()
    dst_addr, dst_port = dst.getsockname()
    while True:
        try:
            buffer = src.recv(0x400)
        except socket.error:
            break
        if len(buffer) == 0:
            logging.debug("[-] No data received! Breaking...")
            break
        try:
            dst.send(buffer)
        except socket.error:
            break
    logging.debug(f"[+] Closing connections! [{src_addr}:{src_port}]")
    try:
        src.shutdown(socket.SHUT_RDWR)
        src.close()
    except socket.error:
        pass
    logging.debug(f"[+] Closing connections! [{dst_addr}:{dst_port}]")
    try:
        dst.shutdown(socket.SHUT_RDWR)
        dst.close()
    except socket.error:
        pass
예제 #5
0
    def receiver(self, login: str, client_sock: socket.socket):
        while self.running:
            try:
                data = client_sock.recv(1024)
            except ConnectionResetError:
                break

            if data == b'stop':
                print('Client {} stopped'.format(login))
                self.connected.remove(client_sock)
                self.players.remove(login)
                try:
                    client_sock.sendall(b'')
                except ConnectionResetError:
                    pass
                break

            decoded = data.decode()
            login, command = list(
                csv.reader(io.StringIO(decoded), delimiter=' ',
                           quotechar='"'))[0]
            if command == 'create':
                self.players.append(login)

            print('Client {} {} sent: "{}"'.format(login,
                                                   client_sock.getsockname(),
                                                   decoded))
            self.received_data.write_end(data)
            time.sleep(0.01)

        print('Stopped receiving from {} {}'.format(login,
                                                    client_sock.getsockname()))
        client_sock.close()
예제 #6
0
def send_message(receiver: socket, sender: socket , data:str) -> None:
    """Send the message as string to the destination"""
    
    prev = {
        "TO": receiver.getsockname(),
        "FROM": sender.getsockname(),
        "WTF": WTF.SEND_TEXT 
        }
    
    
예제 #7
0
 def __init__(self, runner: 'BaseRunner', sock: socket.socket, *,
              shutdown_timeout: float=60.0,
              ssl_context: Optional[SSLContext]=None,
              backlog: int=128) -> None:
     super().__init__(runner, shutdown_timeout=shutdown_timeout,
                      ssl_context=ssl_context, backlog=backlog)
     self._sock = sock
     scheme = 'https' if self._ssl_context else 'http'
     if hasattr(socket, 'AF_UNIX') and sock.family == socket.AF_UNIX:
         name = '{}://unix:{}:'.format(scheme, sock.getsockname())
     else:
         host, port = sock.getsockname()[:2]
         name = str(URL.build(scheme=scheme, host=host, port=port))
     self._name = name
예제 #8
0
 def __init__(self, runner: 'BaseRunner', sock: socket.socket, *,
              shutdown_timeout: float=60.0,
              ssl_context: Optional[SSLContext]=None,
              backlog: int=128) -> None:
     super().__init__(runner, shutdown_timeout=shutdown_timeout,
                      ssl_context=ssl_context, backlog=backlog)
     self._sock = sock
     scheme = 'https' if self._ssl_context else 'http'
     if hasattr(socket, 'AF_UNIX') and sock.family == socket.AF_UNIX:
         name = '{}://unix:{}:'.format(scheme, sock.getsockname())
     else:
         host, port = sock.getsockname()[:2]
         name = str(URL.build(scheme=scheme, host=host, port=port))
     self._name = name
예제 #9
0
    def __listen_to_client(self, client: socket.socket, address: tuple) -> None:
        print("{}Creating new thread for client {}:{}".format(self.__tag, *address), flush=True)

        _client = Client(client, client.getsockname())

        while True:
            try:
                data, _ = receive(client, buffer_size=2048)

                print("{}Received {} from {}:{}".format(self.__tag, data, *address), flush=True)

                if isinstance(data, dict):
                    data = Dict(data)

                    data.data.update({'timestamp': datetime.now()})
                    
                    dir_name = data.source
                    if self.dir_name:
                        dir_name = join_path(self.dir_name, data.source.split("_")[0])
                    
                    save_csv(data.data, data.source, dir_name=dir_name)

                send_to(client, f"OK - {datetime.now()}")

            except:
                # traceback.print_exc()
                addr, port = _client.address
                print(f"\t[ {fg(255, 0, 0)}- {fg.rs}] Unregistered {addr}:{port}", flush=True)
                self.mutex.acquire()
                self.__instances.remove(client)
                self.mutex.release()
                exit(1)
예제 #10
0
def original_addr(csock: socket.socket) -> typing.Tuple[str, int]:
    # Get the original destination on Linux.
    # In theory, this can be done using the following syscalls:
    #     sock.getsockopt(socket.SOL_IP, SO_ORIGINAL_DST, 16)
    #     sock.getsockopt(SOL_IPV6, SO_ORIGINAL_DST, 28)
    #
    # In practice, it is a bit more complex:
    #  1. We cannot rely on sock.family to decide which syscall to use because of IPv4-mapped
    #     IPv6 addresses. If sock.family is AF_INET6 while sock.getsockname() is ::ffff:127.0.0.1,
    #     we need to call the IPv4 version to get a result.
    #  2. We can't just try the IPv4 syscall and then do IPv6 if that doesn't work,
    #     because doing the wrong syscall can apparently crash the whole Python runtime.
    # As such, we use a heuristic to check which syscall to do.
    is_ipv4 = "." in csock.getsockname()[0]  # either 127.0.0.1 or ::ffff:127.0.0.1
    if is_ipv4:
        # the struct returned here should only have 8 bytes, but invoking sock.getsockopt
        # with buflen=8 doesn't work.
        dst = csock.getsockopt(socket.SOL_IP, SO_ORIGINAL_DST, 16)
        port, raw_ip = struct.unpack_from("!2xH4s", dst)
        ip = socket.inet_ntop(socket.AF_INET, raw_ip)
    else:
        dst = csock.getsockopt(SOL_IPV6, SO_ORIGINAL_DST, 28)
        port, raw_ip = struct.unpack_from("!2xH4x16s", dst)
        ip = socket.inet_ntop(socket.AF_INET6, raw_ip)
    return ip, port
예제 #11
0
파일: name.py 프로젝트: MiroslavVitkov/rat
 def _handle(me, s: socket.socket):
     while me.alive:
         me.server.alive = me.alive
         try:
             data = s.recv(1024)
         except:
             # Perhaps the user disconnected.
             pass
         if data:
             # This could be an `ask` or a `register` request.
             try:
                 remote_user = User.from_bytes(data)
                 assert(type(remote_user) == User)
                 me.register(remote_user)
                 print('New user registered:', remote_user)
                 print('Now there are', len(me.users), 'registered users.\n')
             except:
                 regex = data.decode('utf-8')
                 print(s.getsockname(), 'is asking for', regex)
                 r = re.compile(regex)
                 matches = [me.users[u] for u in me.users
                            if r.match(me.users[u].name)]
                 for u in matches:
                     try:
                         bytes = pickle.dumps(u)
                         s.sendall(bytes)
                     except:
                         # Perhaps the user disconnected?
                         continue
                 continue
예제 #12
0
    def match_socket(self,
                     sock: socket.socket,
                     address: IPv6Address,
                     interface: int = 0) -> bool:
        """
        Determine if we can recycle this socket

        :param sock: An existing socket
        :param address: The address we want
        :param interface: The interface number we want
        :return: Whether the socket is suitable
        """
        if sock.family != socket.AF_INET6 or sock.type != self.sock_type or sock.proto != self.sock_proto:
            # Different protocol
            return False

        sockname = sock.getsockname()
        if IPv6Address(sockname[0].split('%')[0]) != address \
                or sockname[1] != self.listen_port \
                or sockname[3] != interface:
            # Wrong address
            return False

        # Amazing! This one seems to match
        return True
예제 #13
0
    def send_user_files(self, user_name: str, connection: socket.socket):
        thread_name = current_thread().name
        print('\t\t{}: Checking files for {}'.format(thread_name,
                                                     connection.getsockname()))

        user_dir = self.get_user_dir(user_name)

        for root, dirs, files in os.walk(user_dir):
            if not files:
                print('\t\t{}: No files to send.'.format(thread_name))
                connection.sendall(
                    json.dumps({
                        'message': communication.RESULTS[6]
                    }).encode())
            else:
                print('\t\t{}: Sending files.'.format(thread_name))
                for file_name in files:

                    # Envia o nome do arquivo
                    print('\t\t{}: Sending file name.'.format(thread_name))
                    connection.sendall(
                        json.dumps({
                            'file_name': file_name
                        }).encode())

                    # Envia os dados do arquivo
                    with open(os.path.join(user_dir, file_name), 'rb') as file:
                        print('\t\t{}: Sending file data.'.format(thread_name))
                        file_data = file.read(communication.BUFFSIZE)

                        while file_data:
                            connection.sendall(file_data)
                            file_data = file.read(communication.BUFFSIZE)
예제 #14
0
def bind_unused_port(sock: socket.socket, host: str = 'localhost') -> int:
    """Bind the socket to a free port and return the port number.
    This code is based on the code in the stdlib's test.test_support module."""
    if sock.family in (socket.AF_INET,
                       socket.AF_INET6) and sock.type == socket.SOCK_STREAM:
        if hasattr(socket, "SO_EXCLUSIVEADDRUSE"):
            try:
                sock.setsockopt(socket.SOL_SOCKET, socket.SO_EXCLUSIVEADDRUSE,
                                1)
            except socket.error:
                pass
    if sock.family == socket.AF_INET:
        if host == 'localhost':
            sock.bind(('127.0.0.1', 0))
        else:
            sock.bind((host, 0))
    elif sock.family == socket.AF_INET6:
        if host == 'localhost':
            sock.bind(('::1', 0, 0, 0))
        else:
            sock.bind((host, 0, 0, 0))
    else:
        raise CommunicationError("unsupported socket family: " +
                                 str(sock.family))
    return sock.getsockname()[1]
예제 #15
0
def process_requests(waiting_socket: socket, handle_message: Callable[[bytes, List[bytes]], bytes]) -> None:
    # FIXME How to recover failures?
    try:
        while True:
            process_request(waiting_socket, handle_message)
    except (ConnectionAbortedError, ConnectionResetError):
        _logger.info("The socket " + str(waiting_socket.getsockname()) + " was closed.")
예제 #16
0
def forward_tcp_to_tcp(source: socket.socket, destination: socket.socket):
    try:
        log.debug("Ongoing connection route: %s ---> %s ---> %s" %
                  (source.getpeername(), source.getsockname(),
                   destination.getpeername()))
    except:
        # Do nothing
        log.debug("Socket closed maybe??")
    message = ' '
    while message:
        message = source.recv(tcp_bufsize)
        if message:
            destination.sendall(message)
        else:
            try:
                source.shutdown(socket.SHUT_RD)
            except:
                # traceback.print_exc()
                pass  # Do nothing then
            try:
                destination.shutdown(socket.SHUT_WR)
            except:
                # traceback.print_exc()
                pass  # Do nothing then
            break
예제 #17
0
    def _recv(self, sock: socket.socket, mask):
        local_addr = sock.getsockname()
        data, addr = sock.recvfrom(65535)       # maximum udp packet size
        session = self._session.get_session((local_addr, addr))
        session: _SessionPeer
        # check if the session exist
        if session is None:
            _logger.info("new session from [%s]:%d" % (addr[0], addr[1]))
            # session not exist, we should create a new relay session
            destination_addrinfo = self._sock_to_destination[sock]
            relay_sock = socket.socket(destination_addrinfo[0], socket.SOCK_DGRAM)
            # send data to the destination at first,
            # so the system will automatically bind a address for that socket
            relay_sock.sendto(data, destination_addrinfo[4])
            relay_local_addr = relay_sock.getsockname()
            session = self._session.create_session((local_addr, addr), sock,
                                                   (relay_local_addr, destination_addrinfo[4]), relay_sock)
            self.__selector.register(relay_sock, selectors.EVENT_READ, self._recv)
            _logger.info("udp session created: [%s]:%d,[%s]:%d <> [%s]:%d,[%s]:%d" %
                         (MultiThreadUDPRelay._format_addr(addr) +
                          MultiThreadUDPRelay._format_addr(local_addr) +
                          MultiThreadUDPRelay._format_addr(relay_local_addr) +
                          MultiThreadUDPRelay._format_addr(destination_addrinfo[4])))
        else:
            session.socket.sendto(data, session.address)

        session.session_info.update(len(data))
예제 #18
0
    def log_startup(sock: socket.socket) -> None:
        all_addresses_message = (
            " * Running on all addresses.\n"
            "   WARNING: This is a development server. Do not use it in"
            " a production deployment.")

        if sock.family == af_unix:
            _log("info", " * Running on %s (Press CTRL+C to quit)", hostname)
        else:
            if hostname == "0.0.0.0":
                _log("warning", all_addresses_message)
                display_hostname = get_interface_ip(socket.AF_INET)
            elif hostname == "::":
                _log("warning", all_addresses_message)
                display_hostname = get_interface_ip(socket.AF_INET6)
            else:
                display_hostname = hostname

            if ":" in display_hostname:
                display_hostname = f"[{display_hostname}]"

            _log(
                "info",
                " * Running on %s://%s:%d/ (Press CTRL+C to quit)",
                "http" if ssl_context is None else "https",
                display_hostname,
                sock.getsockname()[1],
            )
예제 #19
0
def bind_unused_port(
    sock: socket.socket,
    host: Union[str, ipaddress.IPv4Address,
                ipaddress.IPv6Address] = 'localhost'
) -> int:
    """Bind the socket to a free port and return the port number.
    This code is based on the code in the stdlib's test.test_support module."""
    if sock.family in (socket.AF_INET,
                       socket.AF_INET6) and sock.type == socket.SOCK_STREAM:
        if hasattr(socket, "SO_EXCLUSIVEADDRUSE"):
            with contextlib.suppress(socket.error):
                sock.setsockopt(socket.SOL_SOCKET, socket.SO_EXCLUSIVEADDRUSE,
                                1)
    if not isinstance(host, str):
        host = str(host)
    if sock.family == socket.AF_INET:
        if host == 'localhost':
            sock.bind(('127.0.0.1', 0))
        else:
            sock.bind((host, 0))
    elif sock.family == socket.AF_INET6:
        if host == 'localhost':
            sock.bind(('::1', 0, 0, 0))
        else:
            sock.bind((host, 0, 0, 0))
    else:
        raise CommunicationError("unsupported socket family: " +
                                 str(sock.family))
    return sock.getsockname()[1]
예제 #20
0
    def handle_conn(self, client_sock: socket.socket) -> None:
        try:
            client_address = client_sock.getsockname()
            client = self.client_init(client_sock)

            if client:
                self.online[client.username] = client
                th_send = threading.Thread(target=client._sending_thread)
                th_recv = threading.Thread(target=client._receiving_thread)
                th_send.start()
                th_recv.start()
                th_send.join()
                th_recv.join()

                if client.username in self.online:
                    del self.online[client.username]

        except Exception as e:
            traceback.print_exc()
            logging.error(f'Error occured: {e}')

        finally:
            if client:
                logging.info(f'{client_address} has been disconnected...')
                if client.username in self.online:
                    del self.online[client.username]
            client_sock.close()
예제 #21
0
    def __init__(self, server: Server, client_socket: socket.socket):
        """
        Instantiates a new ClientConnection
        :param server: The parent server of the connection
        :param client_socket: The socket of the client that is to be read
        """
        super().__init__(name=str(client_socket.getsockname()))

        self.timestamp = datetime.datetime.now()

        self.server = server
        self.address = client_socket.getsockname()
        self.socket = client_socket

        self.requestSize = None
        self.reader = BufferedReader(client_socket, server.notify_period,
                                     server.buffer_size)
예제 #22
0
def spam_clients(sock: socket.socket, other_clients: List[Tuple[str, int]]):
    # Only other clients should arrive here
    for client in other_clients:
        for x in range(10):
            # Spam them
            msg = "{0} send to {2}, try={1}".format(sock.getsockname(), x,
                                                    client)
            sock.sendto(msg.encode(), client)
def test_call_after_close_raises(receiver_socket: socket.socket,
                                 caplog: Any) -> None:
    host, port = receiver_socket.getsockname()
    client = StatsdClient(host=host, port=port, max_buffer_size=0)
    client._close()

    with pytest.raises(RuntimeError):
        client.increment("foo", 1)
예제 #24
0
 def environ(self, server: socket.socket) -> Dict[bytes, bytes]:
     path = os.fsencode(server.getsockname())
     return collections.OrderedDict((
         (b"NON_DNSMASQ_PREFIX_ENV", b"1"),
         (b"DNSMASQ_PREFIX_ENV", b"2"),
         (b"DNSMASQ_PREFIX_WITH_WHITESPACE", b" \twith\t whitespace\t "),
         (b"DNSMASQ_CHARACTERS", bytes(range(0x01, 0x100))),
         (b"HADES_AUTH_DHCP_SCRIPT_SOCKET", path),
     ))
예제 #25
0
 def __init__(self, conn: socket.socket, other_users, games):
     threading.Thread.__init__(self)
     self.conn = conn
     self.ip_addr, self.port = conn.getsockname()
     self.username = ""
     self.other_users = other_users
     self.dead = False
     self.games = games
     print("[+] New server socket thread started for " + self.ip_addr +
           ":" + str(self.port))
예제 #26
0
 def create_router_ips(self, message: Message, client: socket):
     print("Il SERVER sta generando gli indirizzi IP per %s:%s" %
           client.getsockname())
     content = message.text
     self.prepare_for_next_message_to_client(message)
     message.message_type = MessageType.DHCP_ROUTER_ACK
     publicnetwork = self.generate_client_ip(content, client)
     message.text = "ServerIP:" + self.generate_server_ip(
         publicnetwork) + "\nClienIP:" + publicnetwork
     return message
예제 #27
0
 def _send_msg(self, sock: socket.socket, msg: Any,
               addr: Tuple[str, int]) -> None:
     # @TODO Sent information should be different based on message received
     template = 'Send message to {0}:{1} using interface {2}:{3}.'
     if (isinstance(msg, str)):
         sock.sendto(msg.encode(self._encoding), addr)
     else:
         sock.sendto(msg, addr)
     self._logger.info(
         template.format(addr[0], addr[1], *sock.getsockname()))
def test_no_buffering_sends_immediately(
        receiver_socket: socket.socket) -> None:
    host, port = receiver_socket.getsockname()
    client = StatsdClient(host=host, port=port, max_buffer_size=0)

    client.increment("foo", 1)
    assert _read_from_socket(receiver_socket) == "foo:1|c"
    assert _read_from_socket(receiver_socket) == ""

    client.increment("foo", 2)
    assert _read_from_socket(receiver_socket) == "foo:2|c"
def test_broken_pipe(receiver_socket: socket.socket, caplog: Any) -> None:
    host, port = receiver_socket.getsockname()
    client = StatsdClient(host=host, port=port, max_buffer_size=0)

    with mock.patch("socket.socket.send",
                    side_effect=[2]), caplog.at_level(logging.WARNING):
        # Should not raise.
        client.increment("foo", 1)

    assert len(caplog.records) == 1
    assert "Broken pipe" in caplog.text
예제 #30
0
파일: net.py 프로젝트: giflw/afn-tools
 def __init__(self):
     # Set up the interrupt socket
     interrupt_server = Socket()
     interrupt_server.bind(("localhost", 0))
     interrupt_server.listen(1)
     self.interrupt_writer = Socket()
     self.interrupt_writer.setblocking(False)
     self.interrupt_writer.connect("localhost", interrupt_server.getsockname()[1])
     self.interrupt_reader = interrupt_server.accept()
     interrupt_server.shutdown(SHUT_RDWR)
     interrupt_server.close()
     self.interrupt_reader.setblocking(False)
     self.interrupt_writer.setblocking(False)
def test_socket_errors_are_logged_not_raised(receiver_socket: socket.socket,
                                             caplog: Any) -> None:
    host, port = receiver_socket.getsockname()
    client = StatsdClient(host=host, port=port, max_buffer_size=0)

    with mock.patch("socket.socket.send",
                    side_effect=[socket.error("Broken socket")
                                 ]), caplog.at_level(logging.WARNING):
        # Should not raise.
        client.increment("foo", 1)

    assert len(caplog.records) == 1
    assert "Error sending packet" in caplog.text
예제 #32
0
 def _read(self, sock: socket.socket):
     # socket may not exist in relay table
     if sock not in self.__relay_table:
         return
     _logger.debug("read from sock ('%s':%d)" % _format_addr(sock.getsockname()))
     buffer = self.__send_buffer[self._peer(sock)]
     if buffer['buffer'] is None:
         try:
             buffer['buffer'] = sock.recv(81920)
             _logger.debug("actually read, length: %d" % len(buffer['buffer']))
         except ConnectionAbortedError:
             _logger.info("connection abort while receiving from '%s':%d" % _format_addr(sock.getsockname()))
             buffer['buffer'] = None
         except ConnectionResetError:
             _logger.info("connection reset from '%s':%d" % _format_addr(sock.getsockname()))
             buffer['buffer'] = None
         if not buffer['buffer']:
             _logger.debug("connection closed.")
             buffer['buffer'] = None
         if buffer['buffer'] is None:
             self._clear(sock)
             return
         buffer['send_pos'] = 0
     try:
         buffer['send_pos'] += self._peer(sock).send(buffer['buffer'][buffer['send_pos']:])
     except (ConnectionAbortedError, ConnectionResetError):
         _logger.info("connection abort while sending to '%s':%d" %
                      _format_addr(self.__relay_table[sock].getpeername()))
         self._clear(sock)
         return
     except BlockingIOError:         # send buffer is full
         buffer['send_pos'] = 0      # so the next time we write data to buffer from position 0
     if buffer['send_pos'] == len(buffer['buffer']):     # no more data in buffer
         buffer['buffer'] = None
     else:
         # handle writable event on socket, so we can write to the socket as fast as possible
         self.__selector.modify(self._peer(sock), selectors.EVENT_WRITE | selectors.EVENT_READ, self._relay_handle)
     self.__send_buffer[self._peer(sock)] = buffer
def test_unexpected_exceptions_are_logged_not_raised(
        receiver_socket: socket.socket, caplog: Any) -> None:
    host, port = receiver_socket.getsockname()
    client = StatsdClient(host=host, port=port, max_buffer_size=0)

    with mock.patch("socket.socket.send",
                    side_effect=[ValueError("Random error")
                                 ]), caplog.at_level(logging.ERROR):
        # Should not raise.
        client.increment("foo", 1)

    assert len(caplog.records) == 1
    assert "Traceback (most recent call last)" in caplog.text
    assert "ValueError: Random error" in caplog.text
예제 #34
0
    def match_socket(self, sock: socket.socket, address: IPv6Address, interface: int = 0) -> bool:
        """
        Determine if we can recycle this socket

        :param sock: An existing socket
        :param address: The address we want
        :param interface: The interface number we want
        :return: Whether the socket is suitable
        """
        if sock.family != socket.AF_INET6 or sock.type != self.sock_type or sock.proto != self.sock_proto:
            # Different protocol
            return False

        sockname = sock.getsockname()
        if IPv6Address(sockname[0].split('%')[0]) != address \
                or sockname[1] != self.listen_port \
                or sockname[3] != interface:
            # Wrong address
            return False

        # Amazing! This one seems to match
        return True
예제 #35
0
파일: tcpscan.py 프로젝트: jftuga/universe
def tcp_connect_handler(sock:socket.socket, remote:list, server:socketserver.TCPServer):
	now = time.strftime("%Y-%m-%d %H:%M:%S")
	print("[%s] Incoming connection on %s:%s from %s:%s" % (now,sock.getsockname()[0],sock.getsockname()[1],remote[0],remote[1]))
	#sock.shutdown(socket.SHUT_RDWR)
	sock.close()