def _write_inner_frame(self, opcode, payload, end=True):
        payload_length = len(payload)
        write_position = 0

        try:
            # An inner frame will be fragmented if there is no enough send
            # quota. This semaphore ensures that fragmented inner frames are
            # sent in order on the logical channel.
            # Note that frames that come from other logical channels or
            # multiplexing control blocks can be inserted between fragmented
            # inner frames on the physical channel.
            self._write_inner_frame_semaphore.acquire()

            # Consume an octet quota when this is the first fragmented frame.
            if opcode != common.OPCODE_CONTINUATION:
                try:
                    self._send_condition.acquire()
                    while (not self._send_closed) and self._send_quota == 0:
                        self._send_condition.wait()

                    if self._send_closed:
                        raise BadOperationException(
                            'Logical connection %d is closed' %
                            self._request.channel_id)

                    self._send_quota -= 1
                finally:
                    self._send_condition.release()

            while write_position < payload_length:
                try:
                    self._send_condition.acquire()
                    while (not self._send_closed) and self._send_quota == 0:
                        self._logger.debug(
                            'No quota. Waiting FlowControl message for %d.' %
                            self._request.channel_id)
                        self._send_condition.wait()

                    if self._send_closed:
                        raise BadOperationException(
                            'Logical connection %d is closed' %
                            self.request._channel_id)

                    remaining = payload_length - write_position
                    write_length = min(self._send_quota, remaining)
                    inner_frame_end = (
                        end and
                        (write_position + write_length == payload_length))

                    inner_frame = self._create_inner_frame(
                        opcode,
                        payload[write_position:write_position+write_length],
                        inner_frame_end)
                    self._send_quota -= write_length
                    self._logger.debug('Consumed quota=%d, remaining=%d' %
                                       (write_length, self._send_quota))
                finally:
                    self._send_condition.release()

                # Writing data will block the worker so we need to release
                # _send_condition before writing.
                self._logger.debug('Sending inner frame: %r' % inner_frame)
                self._request.connection.write(inner_frame)
                write_position += write_length

                opcode = common.OPCODE_CONTINUATION

        except ValueError, e:
            raise BadOperationException(e)
        finally:
            self._write_inner_frame_semaphore.release()
dataset/ETHPy150Open google/pywebsocket/mod_pywebsocket/mux.py/_LogicalStream._write_inner_frame/original