コード例 #1
0
ファイル: server.py プロジェクト: billybimbob/file-share
def path_connection(path: Path) \
    -> Callable[[aio.StreamReader, aio.StreamWriter], Coroutine[Any, Any, None]]:
    """
    Creates a stream callback, and specifying the path for the server directory
    """
    return (lambda reader, writer:
        server_connection(path, StreamPair(reader, writer)))
コード例 #2
0
        async def to_receiver(reader: aio.StreamReader,
                              writer: aio.StreamWriter):
            """ Switch to determine which receiver to use """
            conn = StreamPair(reader, writer)
            login = await Message[Login].read(reader)  # TODO: add try except

            await self._peer_receiver(login, conn)
コード例 #3
0
    async def _connect_index(self, host: str) -> IndexerConnection:
        """ Establishes a connection with the indexer peer """
        start = self._index_start

        logging.info(f'trying connection with indexer at {start}')

        in_pair = await aio.open_connection(start.host, start.port)
        in_pair = StreamPair(*in_pair)
        logging.info(f'connection with indexer')

        login = Login(self._user, host, self._port)
        await Message.write(in_pair.writer, login)

        return IndexerConnection(start, in_pair)
コード例 #4
0
    async def _peer_download(self, filename: str, target: tuple[str, int]):
        """ Client-side connection with any of the other peers """
        logging.debug(f"attempting connection to {target}")

        fin, pend = await aio.wait({aio.open_connection(*target)}, timeout=8)
        for p in pend:
            p.cancel()

        if len(fin) == 0:
            logging.error('connection attempt failed')
            return

        pair = fin.pop().result()  # will only be one result
        pair = StreamPair(*pair)
        reader, writer = pair

        log = logging.getLogger()

        try:
            await Message.write(writer, self.user)
            user = await Message.read(reader, str)

            log = logging.getLogger(user)
            log.debug("connected")

            await self._receive_file_retries(filename, pair, log)

        except Exception as e:
            logging.exception(e)

        finally:
            if not reader.at_eof():
                writer.write_eof()

            writer.close()
            await writer.wait_closed()
            log.debug("disconnected")
コード例 #5
0
    async def _peer_download(self, filepath: Path, target: Location,
                             *chunks: File.Chunk) -> Optional[bytes]:
        """ Client-side connection with any of the other peers """

        log = logging.getLogger()
        try:
            self._check_chunks(target, *chunks)

            logging.debug(f"attempting connection to {target}")
            pair = await aio.open_connection(target.host, target.port)
            pair = StreamPair(*pair)
            reader, writer = pair

            try:
                await Message.write(writer, self._user)
                user = await Message[str].read(reader)

                log = logging.getLogger(user)
                log.debug("connected as client")

                return await self._download_requests(pair,
                                                     filepath,
                                                     *chunks,
                                                     log=log)

            finally:
                if not reader.at_eof():
                    writer.write_eof()

                writer.close()
                await writer.wait_closed()
                log.debug("disconnected as client")

        except Exception as e:
            log.exception(e)
            raise e
コード例 #6
0
ファイル: client.py プロジェクト: billybimbob/file-share
async def open_connection(
    user: Optional[str], address: Optional[str], port: int, directory: str,
    workers: int, retries: int, timeout: int,
    log: str, verbosity: int, *args: Any, **kwargs: Any):
    """ Attempts to connect to a server with the given args """
    try:
        user, host, num_sockets, path = process_args(user, address, workers, directory)
        init_log(log, verbosity)
        sockets: list[StreamPair] = []

        for _ in range(num_sockets):
            pair = await aio.open_connection(host, port)
            pair = StreamPair(*pair)
            sockets.append(pair)
            await Message.write(pair.writer, user)

        # closes socket in session
        await client_session(path, sockets, retries, timeout)

    except Exception as e:
        logging.error(e)

    finally:
        logging.info('ending connection')
コード例 #7
0
 def to_upload(reader: aio.StreamReader, writer: aio.StreamWriter):
     """ Weak peer closure as a stream callback """
     return self._peer_upload(StreamPair(reader, writer))
コード例 #8
0
    async def start_server(self):
        """
        Connects the peer to the indexing node, and starts the peer server
        """
        # async sync state needs to be init from async context
        self.dir_update = aio.Event()

        def to_upload(reader: aio.StreamReader, writer: aio.StreamWriter):
            """ Indexer closure as a stream callback """
            return self._peer_upload(StreamPair(reader, writer))

        try:
            host = socket.gethostname()
            server = await aio.start_server(to_upload,
                                            host,
                                            self.port,
                                            start_serving=False)
            logging.info(f'peer server on {host}, port {self.port}')

            async with server:
                start = self.index_start
                logging.info(f'trying connection with indexer at {start}')

                done, pend = await aio.wait(
                    {aio.open_connection(start.host, start.port)}, timeout=8)

                for p in pend:
                    p.cancel()
                if len(done) == 0:
                    return

                in_pair = done.pop().result()
                in_pair = StreamPair(*in_pair)

                indexer = IndexState(start, in_pair)

                login = Login(self.user, host, self.port)
                await Message.write(in_pair.writer, login)

                # make sure that event is listening before it can be set and cleared
                first_update = aio.create_task(self.dir_update.wait())

                sender = aio.create_task(self._send_dir(indexer))
                checker = aio.create_task(self._check_dir())

                # only accept connections and user input after a dir_update
                # should not deadlock, keep eye on
                await first_update
                await server.start_serving()

                session = aio.create_task(self._session(indexer))
                conn = aio.create_task(self._watch_connection(indexer))

                await aio.wait([session, conn],
                               return_when=aio.FIRST_COMPLETED)

                checker.cancel()
                sender.cancel()

                if not session.done(): session.cancel()
                if not conn.done(): conn.cancel()

            await server.wait_closed()

        except Exception as e:
            logging.exception(e)
            for task in aio.all_tasks():
                task.cancel()

        finally:
            logging.debug("disconnected from indexing server")
            logging.debug("ending peer")