def add_channel(self, channel_id, options):
        if not self._is_active:
            raise Exception('Mux client is not active')

        if channel_id in self._logical_channels:
            raise Exception('Channel id %d already exists' % channel_id)

        try:
            send_quota = self._channel_slots.popleft()
        except IndexError, e:
            raise Exception('No channel slots: %r' % e)

        # Create AddChannel request
        request_line = 'GET %s HTTP/1.1\r\n' % options.resource
        fields = []
        if options.server_port == client_for_testing.DEFAULT_PORT:
            fields.append('Host: %s\r\n' % options.server_host.lower())
        else:
            fields.append('Host: %s:%d\r\n' % (options.server_host.lower(),
                                               options.server_port))
        fields.append('Origin: %s\r\n' % options.origin.lower())
        fields.append('Connection: Upgrade\r\n')

        if len(options.extensions) > 0:
            fields.append('Sec-WebSocket-Extensions: %s\r\n' %
                          ', '.join(options.extensions))

        handshake = request_line + ''.join(fields) + '\r\n'
        add_channel_request = _create_add_channel_request(
            channel_id, handshake)
        payload = _encode_channel_id(_CONTROL_CHANNEL_ID) + add_channel_request
        self._stream.send_binary(payload)

        # Wait AddChannelResponse
        self._logger.debug('Waiting AddChannelResponse for the request...')
        response = None
        try:
            self._control_blocks_condition.acquire()
            while True:
                for block in self._control_blocks:
                    if block.opcode != _MUX_OPCODE_ADD_CHANNEL_RESPONSE:
                        continue
                    if block.channel_id == channel_id:
                        response = block
                        self._control_blocks.remove(response)
                        break
                if response:
                    break
                self._control_blocks_condition.wait(self._timeout)
                if not self._is_active:
                    raise Exception('AddChannelRequest timed out')
        finally:
            self._control_blocks_condition.release()

        # Validate AddChannelResponse
        if response.rejected:
            raise Exception('The server rejected AddChannelRequest')

        fields = _parse_handshake_response(response.encoded_handshake)

        # Should we reject when Upgrade, Connection, or Sec-WebSocket-Accept
        # headers exist?

        self._logical_channels_condition.acquire()
        self._logical_channels[channel_id] = _LogicalChannelData()
        self._logical_channels[channel_id].send_quota = send_quota
        self._logical_channels_condition.release()

        self._logger.debug('Logical channel %d established' % channel_id)
dataset/ETHPy150Open google/pywebsocket/test/mux_client_for_testing.py/MuxClient.add_channel/original