# Buggy code
async def send(self, message):
    await self.writable.wait()

    message_type = message["type"]

    if not self.handshake_complete:
        if message_type == "websocket.accept":
            self.logger.info(
                '%s - "WebSocket %s" [accepted]',
                self.scope["client"],
                self.scope["root_path"] + self.scope["path"],
            )
            self.handshake_complete = True
            subprotocol = message.get("subprotocol")
            output = self.conn.send(
                wsproto.events.AcceptConnection(
                    subprotocol=subprotocol, extensions=[PerMessageDeflate()]
                )
            )
            self.transport.write(output)

        elif message_type == "websocket.close":
            self.queue.put_nowait({"type": "websocket.disconnect", "code": None})
            self.logger.info(
                '%s - "WebSocket %s" 403',
                self.scope["client"],
                self.scope["root_path"] + self.scope["path"],
            )
            self.handshake_complete = True
            self.close_sent = True
            msg = h11.Response(status_code=403, headers=[])
            output = self.conn.send(msg)
            msg = h11.EndOfMessage()
            output += self.conn.send(msg)
            self.transport.write(output)
            self.transport.close()

        else:
            msg = (
                "Expected ASGI message 'websocket.accept' or 'websocket.close', "
                "but got '%s'."
            )
            raise RuntimeError(msg % message_type)

    elif not self.close_sent:
        if message_type == "websocket.send":
            bytes_data = message.get("bytes")
            text_data = message.get("text")
            data = text_data if bytes_data is None else bytes_data
            output = self.conn.send(wsproto.events.Message(data=data))
            if not self.transport.is_closing():
                self.transport.write(output)

        elif message_type == "websocket.close":
            self.close_sent = True
            code = message.get("code", 1000)
            self.queue.put_nowait({"type": "websocket.disconnect", "code": code})
            output = self.conn.send(wsproto.events.CloseConnection(code=code))
            if not self.transport.is_closing():
                self.transport.write(output)
                self.transport.close()

        else:
            msg = (
                "Expected ASGI message 'websocket.send' or 'websocket.close',"
                " but got '%s'."
            )
            raise RuntimeError(msg % message_type)

    else:
        msg = "Unexpected ASGI message '%s', after sending 'websocket.close'."
        raise RuntimeError(msg % message_type)


# Traceback (TypeError)
Traceback (most recent call last):
File "/home/ossi/src/channels-examples/.venv/lib/python3.7/site-packages/uvicorn/protocols/websockets/websockets_impl.py", line 140, in run_asgi
result = await asgi(self.asgi_receive, self.asgi_send)
File "/home/ossi/src/channels-examples/.venv/lib/python3.7/site-packages/channels/sessions.py", line 179, in __call__
return await self.inner(receive, self.send)
File "/home/ossi/src/channels-examples/.venv/lib/python3.7/site-packages/channels/middleware.py", line 41, in coroutine_call
await inner_instance(receive, send)
File "/home/ossi/src/channels-examples/.venv/lib/python3.7/site-packages/channels/consumer.py", line 59, in __call__
[receive, self.channel_receive], self.dispatch
File "/home/ossi/src/channels-examples/.venv/lib/python3.7/site-packages/channels/utils.py", line 59, in await_many_dispatch
await task
File "/home/ossi/src/channels-examples/.venv/lib/python3.7/site-packages/channels/utils.py", line 51, in await_many_dispatch
result = task.result()
File "/home/ossi/src/channels-examples/.venv/lib/python3.7/site-packages/uvicorn/protocols/websockets/websockets_impl.py", line 222, in asgi_receive
data = await self.recv()
File "/home/ossi/src/channels-examples/.venv/lib/python3.7/site-packages/websockets/protocol.py", line 419, in recv
return_when=asyncio.FIRST_COMPLETED,
File "/usr/lib/python3.7/asyncio/tasks.py", line 361, in wait
fs = {ensure_future(f, loop=loop) for f in set(fs)}
File "/usr/lib/python3.7/asyncio/tasks.py", line 361, in <setcomp>
fs = {ensure_future(f, loop=loop) for f in set(fs)}
File "/usr/lib/python3.7/asyncio/tasks.py", line 592, in ensure_future
raise TypeError('An asyncio.Future, a coroutine or an awaitable is '
TypeError: An asyncio.Future, a coroutine or an awaitable is required

# Fixed code
async def send(self, message):
    await self.writable.wait()

    message_type = message["type"]

    if not self.handshake_complete:
        if message_type == "websocket.accept":
            self.logger.info(
                '%s - "WebSocket %s" [accepted]',
                self.scope["client"],
                self.scope["root_path"] + self.scope["path"],
            )
            self.handshake_complete = True
            subprotocol = message.get("subprotocol")
            output = self.conn.send(
                wsproto.events.AcceptConnection(
                    subprotocol=subprotocol, extensions=[PerMessageDeflate()]
                )
            )
            self.transport.write(output)

        elif message_type == "websocket.close":
            self.queue.put_nowait({"type": "websocket.disconnect", "code": None})
            self.logger.info(
                '%s - "WebSocket %s" 403',
                self.scope["client"],
                self.scope["root_path"] + self.scope["path"],
            )
            self.handshake_complete = True
            self.close_sent = True
            msg = events.RejectConnection(status_code=403, headers=[])
            output = self.conn.send(msg)
            self.transport.write(output)
            self.transport.close()

        else:
            msg = (
                "Expected ASGI message 'websocket.accept' or 'websocket.close', "
                "but got '%s'."
            )
            raise RuntimeError(msg % message_type)

    elif not self.close_sent:
        if message_type == "websocket.send":
            bytes_data = message.get("bytes")
            text_data = message.get("text")
            data = text_data if bytes_data is None else bytes_data
            output = self.conn.send(wsproto.events.Message(data=data))
            if not self.transport.is_closing():
                self.transport.write(output)

        elif message_type == "websocket.close":
            self.close_sent = True
            code = message.get("code", 1000)
            self.queue.put_nowait({"type": "websocket.disconnect", "code": code})
            output = self.conn.send(wsproto.events.CloseConnection(code=code))
            if not self.transport.is_closing():
                self.transport.write(output)
                self.transport.close()

        else:
            msg = (
                "Expected ASGI message 'websocket.send' or 'websocket.close',"
                " but got '%s'."
            )
            raise RuntimeError(msg % message_type)

    else:
        msg = "Unexpected ASGI message '%s', after sending 'websocket.close'."
        raise RuntimeError(msg % message_type)