<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def fail_connection(self, code: int = 1006, reason: str = "") -> None: """ 7.1.7. Fail the WebSocket Connection This requires: 1. Stopping all processing of incoming data, which means cancelling :attr:`transfer_data_task`. The close code will be 1006 unless a close frame was received earlier. 2. Sending a close frame with an appropriate code if the opening handshake succeeded and the other side is likely to process it. 3. Closing the connection. :meth:`close_connection` takes care of this once :attr:`transfer_data_task` exits after being canceled. (The specification describes these steps in the opposite order.) """

        logger.debug(
            "%s ! failing %s WebSocket connection with code %d",
            self.side,
            self.state.name,
            code,
        )

        # Cancel transfer_data_task if the opening handshake succeeded.
        # cancel() is idempotent and ignored if the task is done already.
        if hasattr(self, "transfer_data_task"):
            self.transfer_data_task.cancel()

        # Send a close frame when the state is OPEN (a close frame was already
        # sent if it's CLOSING), except when failing the connection because of
        # an error reading from or writing to the network.
        # Don't send a close frame if the connection is broken.
        if code != 1006 and self.state is State.OPEN:

            frame_data = serialize_close(code, reason)

            # Write the close frame without draining the write buffer.

            # Keeping fail_connection() synchronous guarantees it can't
            # get stuck and simplifies the implementation of the callers.
            # Not drainig the write buffer is acceptable in this context.

            # This duplicates a few lines of code from write_close_frame()
            # and write_frame().

            self.state = State.CLOSING
            logger.debug("%s - state = CLOSING", self.side)

            frame = Frame(True, OP_CLOSE, frame_data)
            logger.debug("%s > %r", self.side, frame)
            frame.write(
                self.writer.write, mask=self.is_client, extensions=self.extensions
            )

        # Start close_connection_task if the opening handshake didn't succeed.
        if not hasattr(self, "close_connection_task"):
            self.close_connection_task = self.loop.create_task(self.close_connection())