# Path: server/websockets/compatibility.py

# 
# Path: server/websockets/exceptions.py
# class InvalidHandshake(Exception):
#     """
#     Exception raised when a handshake request or response is invalid.
# 
#     """
# 
# class InvalidOrigin(InvalidHandshake):
#     """
#     Exception raised when the origin in a handshake request is forbidden.
# 
#     """
# 
# Path: server/websockets/handshake.py
# def build_response(set_header, key):
#     """
#     Build a handshake response to send to the client.
# 
#     ``key`` comes from :func:`check_request`.
# 
#     """
#     set_header('Upgrade', 'WebSocket')
#     set_header('Connection', 'Upgrade')
#     set_header('Sec-WebSocket-Accept', accept(key))
# 
# def check_request(get_header):
#     """
#     Check a handshake request received from the client.
# 
#     If the handshake is valid, this function returns the ``key`` which must be
#     passed to :func:`build_response`.
# 
#     Otherwise it raises an :exc:`~websockets.exceptions.InvalidHandshake`
#     exception and the server must return an error like 400 Bad Request.
# 
#     This function doesn't verify that the request is an HTTP/1.1 or higher GET
#     request and doesn't perform Host and Origin checks. These controls are
#     usually performed earlier in the HTTP request handling code. They're the
#     responsibility of the caller.
# 
#     """
#     try:
#         assert get_header('Upgrade').lower() == 'websocket'
#         assert any(
#             token.strip() == 'upgrade'
#             for token in get_header('Connection').lower().split(','))
#         key = get_header('Sec-WebSocket-Key')
#         assert len(base64.b64decode(key.encode(), validate=True)) == 16
#         assert get_header('Sec-WebSocket-Version') == '13'
#     except Exception as exc:
#         raise InvalidHandshake("Invalid request") from exc
#     else:
#         return key
# 
# Path: server/websockets/http.py
# USER_AGENT = ' '.join((
#     'Python/{}'.format(sys.version[:3]),
#     'websockets/{}'.format(websockets_version),
# ))
# 
# @asyncio.coroutine
# def read_request(stream):
#     """
#     Read an HTTP/1.1 request from ``stream``.
# 
#     Return ``(path, headers)`` where ``path`` is a :class:`str` and
#     ``headers`` is a :class:`~email.message.Message`. ``path`` isn't
#     URL-decoded.
# 
#     Raise an exception if the request isn't well formatted.
# 
#     The request is assumed not to contain a body.
# 
#     """
#     request_line, headers = yield from read_message(stream)
#     method, path, version = request_line[:-2].decode().split(None, 2)
#     if method != 'GET':
#         raise ValueError("Unsupported method")
#     if version != 'HTTP/1.1':
#         raise ValueError("Unsupported HTTP version")
#     return path, headers
# 
# Path: server/websockets/protocol.py
# CONNECTING, OPEN, CLOSING, CLOSED = range(4)
# class WebSocketCommonProtocol(asyncio.StreamReaderProtocol):
#     def __init__(self, *,
#                  host=None, port=None, secure=None,
#                  timeout=10, max_size=2 ** 20, max_queue=2 ** 5,
#                  loop=None, legacy_recv=False):
#     def local_address(self):
#     def remote_address(self):
#     def open(self):
#     def state_name(self):
#     def close(self, code=1000, reason=''):
#     def recv(self):
#     def send(self, data):
#     def ping(self, data=None):
#     def pong(self, data=b''):
#     def encode_data(self, data):
#     def ensure_open(self):
#     def run(self):
#     def read_message(self):
#                 def append(frame):
#                 def append(frame):
#                 def append(frame):
#                 def append(frame):
#     def read_data_frame(self, max_size):
#     def read_frame(self, max_size):
#     def write_frame(self, opcode, data=b''):
#     def close_connection(self, force=False):
#     def fail_connection(self, code=1011, reason=''):
#     def client_connected(self, reader, writer):
#     def eof_received(self):
#     def connection_lost(self, exc):


import asyncio
import collections.abc
import email.message
import logging
from .compatibility import asyncio_ensure_future
from .exceptions import InvalidHandshake, InvalidOrigin
from .handshake import build_response, check_request
from .http import USER_AGENT, read_request
from .protocol import CONNECTING, OPEN, WebSocketCommonProtocol
                self.subprotocol = self.select_subprotocol(
                    client_subprotocols, subprotocols)

        headers = []
        set_header = lambda k, v: headers.append((k, v))
        set_header('Server', USER_AGENT)
        if self.subprotocol:
            set_header('Sec-WebSocket-Protocol', self.subprotocol)
        if extra_headers is not None:
            if callable(extra_headers):
                extra_headers = extra_headers(path, self.raw_request_headers)
            if isinstance(extra_headers, collections.abc.Mapping):
                extra_headers = extra_headers.items()
            for name, value in extra_headers:
                set_header(name, value)
        build_response(set_header, key)

        self.response_headers = email.message.Message()
        for name, value in headers:
            self.response_headers[name] = value
        self.raw_response_headers = headers

        # Send handshake response. Since the status line and headers only
        # contain ASCII characters, we can keep this simple.
        response = ['HTTP/1.1 101 Switching Protocols']
        response.extend('{}: {}'.format(k, v) for k, v in headers)
        response.append('\r\n')
        response = '\r\n'.join(response).encode()
        self.writer.write(response)


# Path: server/websockets/compatibility.py

# 
# Path: server/websockets/exceptions.py
# class InvalidHandshake(Exception):
#     """
#     Exception raised when a handshake request or response is invalid.
# 
#     """
# 
# class InvalidOrigin(InvalidHandshake):
#     """
#     Exception raised when the origin in a handshake request is forbidden.
# 
#     """
# 
# Path: server/websockets/handshake.py
# def build_response(set_header, key):
#     """
#     Build a handshake response to send to the client.
# 
#     ``key`` comes from :func:`check_request`.
# 
#     """
#     set_header('Upgrade', 'WebSocket')
#     set_header('Connection', 'Upgrade')
#     set_header('Sec-WebSocket-Accept', accept(key))
# 
# def check_request(get_header):
#     """
#     Check a handshake request received from the client.
# 
#     If the handshake is valid, this function returns the ``key`` which must be
#     passed to :func:`build_response`.
# 
#     Otherwise it raises an :exc:`~websockets.exceptions.InvalidHandshake`
#     exception and the server must return an error like 400 Bad Request.
# 
#     This function doesn't verify that the request is an HTTP/1.1 or higher GET
#     request and doesn't perform Host and Origin checks. These controls are
#     usually performed earlier in the HTTP request handling code. They're the
#     responsibility of the caller.
# 
#     """
#     try:
#         assert get_header('Upgrade').lower() == 'websocket'
#         assert any(
#             token.strip() == 'upgrade'
#             for token in get_header('Connection').lower().split(','))
#         key = get_header('Sec-WebSocket-Key')
#         assert len(base64.b64decode(key.encode(), validate=True)) == 16
#         assert get_header('Sec-WebSocket-Version') == '13'
#     except Exception as exc:
#         raise InvalidHandshake("Invalid request") from exc
#     else:
#         return key
# 
# Path: server/websockets/http.py
# USER_AGENT = ' '.join((
#     'Python/{}'.format(sys.version[:3]),
#     'websockets/{}'.format(websockets_version),
# ))
# 
# @asyncio.coroutine
# def read_request(stream):
#     """
#     Read an HTTP/1.1 request from ``stream``.
# 
#     Return ``(path, headers)`` where ``path`` is a :class:`str` and
#     ``headers`` is a :class:`~email.message.Message`. ``path`` isn't
#     URL-decoded.
# 
#     Raise an exception if the request isn't well formatted.
# 
#     The request is assumed not to contain a body.
# 
#     """
#     request_line, headers = yield from read_message(stream)
#     method, path, version = request_line[:-2].decode().split(None, 2)
#     if method != 'GET':
#         raise ValueError("Unsupported method")
#     if version != 'HTTP/1.1':
#         raise ValueError("Unsupported HTTP version")
#     return path, headers
# 
# Path: server/websockets/protocol.py
# CONNECTING, OPEN, CLOSING, CLOSED = range(4)
# class WebSocketCommonProtocol(asyncio.StreamReaderProtocol):
#     def __init__(self, *,
#                  host=None, port=None, secure=None,
#                  timeout=10, max_size=2 ** 20, max_queue=2 ** 5,
#                  loop=None, legacy_recv=False):
#     def local_address(self):
#     def remote_address(self):
#     def open(self):
#     def state_name(self):
#     def close(self, code=1000, reason=''):
#     def recv(self):
#     def send(self, data):
#     def ping(self, data=None):
#     def pong(self, data=b''):
#     def encode_data(self, data):
#     def ensure_open(self):
#     def run(self):
#     def read_message(self):
#                 def append(frame):
#                 def append(frame):
#                 def append(frame):
#                 def append(frame):
#     def read_data_frame(self, max_size):
#     def read_frame(self, max_size):
#     def write_frame(self, opcode, data=b''):
#     def close_connection(self, force=False):
#     def fail_connection(self, code=1011, reason=''):
#     def client_connected(self, reader, writer):
#     def eof_received(self):
#     def connection_lost(self, exc):


# Path: server/websockets/server.py
import asyncio
import collections.abc
import email.message
import logging
from .compatibility import asyncio_ensure_future
from .exceptions import InvalidHandshake, InvalidOrigin
from .handshake import build_response, check_request
from .http import USER_AGENT, read_request
from .protocol import CONNECTING, OPEN, WebSocketCommonProtocol

                self.subprotocol = self.select_subprotocol(
                    client_subprotocols, subprotocols)

        headers = []
        set_header = lambda k, v: headers.append((k, v))
        set_header('Server', USER_AGENT)
        if self.subprotocol:
            set_header('Sec-WebSocket-Protocol', self.subprotocol)
        if extra_headers is not None:
            if callable(extra_headers):
                extra_headers = extra_headers(path, self.raw_request_headers)
            if isinstance(extra_headers, collections.abc.Mapping):
                extra_headers = extra_headers.items()
            for name, value in extra_headers:
                set_header(name, value)
        build_response(set_header, key)

        self.response_headers = email.message.Message()
        for name, value in headers:
            self.response_headers[name] = value
        self.raw_response_headers = headers

        # Send handshake response. Since the status line and headers only
        # contain ASCII characters, we can keep this simple.
        response = ['HTTP/1.1 101 Switching Protocols']
        response.extend('{}: {}'.format(k, v) for k, v in headers)
        response.append('\r\n')
        response = '\r\n'.join(response).encode()
        self.writer.write(response)


        assert self.state == CONNECTING