<commit_before>import asyncio
from struct import pack, unpack

from pyee import EventEmitter


# message types
DATA_CHANNEL_ACK = 2
DATA_CHANNEL_OPEN = 3

# channel types
DATA_CHANNEL_RELIABLE = 0

WEBRTC_DCEP = 50
WEBRTC_STRING = 51
WEBRTC_BINARY = 53
WEBRTC_STRING_EMPTY = 56
WEBRTC_BINARY_EMPTY = 57


class DataChannelManager:
    def __init__(self, pc, endpoint):
        self.channels = {}
        self.endpoint = endpoint
        self.pc = pc
        if endpoint.is_server:
            self.stream_id = 0
        else:
            self.stream_id = 1

    def create_channel(self, label, protocol):
        # register channel
        channel = RTCDataChannel(id=self.stream_id, label=label, protocol=protocol,
                                 manager=self)
        self.channels[channel.id] = channel
        self.stream_id += 2

        # open channel
        data = pack('!BBHLHH', DATA_CHANNEL_OPEN, DATA_CHANNEL_RELIABLE,
                    0, 0, len(label), len(protocol))
        data += label.encode('utf8')
        data += protocol.encode('utf8')
        asyncio.ensure_future(self.endpoint.send(channel.id, WEBRTC_DCEP, data))

        return channel

    def send(self, channel, data):
        if data == '':
            asyncio.ensure_future(self.endpoint.send(channel.id, WEBRTC_STRING_EMPTY, b'\x00'))
        elif isinstance(data, str):
            asyncio.ensure_future(self.endpoint.send(channel.id, WEBRTC_STRING,
                                                     data.encode('utf8')))
        elif data == b'':
            asyncio.ensure_future(self.endpoint.send(channel.id, WEBRTC_BINARY_EMPTY, b'\x00'))
        elif isinstance(data, bytes):
            asyncio.ensure_future(self.endpoint.send(channel.id, WEBRTC_BINARY, data))
        else:
            raise ValueError('Cannot send unsupported data type: %s' % type(data))

    async def run(self, endpoint):
        self.endpoint = endpoint
        while True:
            stream_id, pp_id, data = await self.endpoint.recv()
            if pp_id == WEBRTC_DCEP and len(data):
                msg_type = unpack('!B', data[0:1])[0]
                if msg_type == DATA_CHANNEL_OPEN and len(data) >= 12:
                    # one side should be using even IDs, the other odd IDs
                    assert (stream_id % 2) != (self.stream_id % 2)
                    assert stream_id not in self.channels

                    (msg_type, channel_type, priority, reliability,
                     label_length, protocol_length) = unpack('!BBHLHH', data[0:12])
                    pos = 12
                    label = data[pos:pos + label_length].decode('utf8')
                    pos += label_length
                    protocol = data[pos:pos + protocol_length].decode('utf8')

                    # register channel
                    channel = RTCDataChannel(id=stream_id, label=label, protocol=protocol,
                                             manager=self)
                    self.channels[stream_id] = channel

                    # emit channel
                    self.pc.emit('datachannel', channel)
            elif pp_id == WEBRTC_STRING and stream_id in self.channels:
                # emit message
                self.channels[stream_id].emit('message', data.decode('utf8'))
            elif pp_id == WEBRTC_STRING_EMPTY and stream_id in self.channels:
                # emit message
                self.channels[stream_id].emit('message', '')
            elif pp_id == WEBRTC_BINARY and stream_id in self.channels:
                # emit message
                self.channels[stream_id].emit('message', data)
            elif pp_id == WEBRTC_BINARY_EMPTY and stream_id in self.channels:
                # emit message
                self.channels[stream_id].emit('message', b'')


class RTCDataChannel(EventEmitter):
    def __init__(self, id, label, protocol, manager, loop=None):
        super().__init__(loop=loop)
        self.__id = id
        self.__label = label
        self.__manager = manager
        self.__protocol = protocol

    def close(self):
        pass

    def send(self, data):
        self.__manager.send(self, data)

    @property
    def id(self):
        """
        An ID number which uniquely identifies the data channel.
        """
        return self.__id

    @property
    def label(self):
        """
        A name describing the data channel.

        These labels are not required to be unique.
        """
        return self.__label

    @property
    def protocol(self):
        """
        The name of the subprotocol in use.
        """
        return self.__protocol
<commit_msg>[datachannel] send ACK for channel establishment<commit_after>import asyncio
from struct import pack, unpack

from pyee import EventEmitter


# message types
DATA_CHANNEL_ACK = 2
DATA_CHANNEL_OPEN = 3

# channel types
DATA_CHANNEL_RELIABLE = 0

WEBRTC_DCEP = 50
WEBRTC_STRING = 51
WEBRTC_BINARY = 53
WEBRTC_STRING_EMPTY = 56
WEBRTC_BINARY_EMPTY = 57


class DataChannelManager:
    def __init__(self, pc, endpoint):
        self.channels = {}
        self.endpoint = endpoint
        self.pc = pc
        if endpoint.is_server:
            self.stream_id = 0
        else:
            self.stream_id = 1

    def create_channel(self, label, protocol):
        # register channel
        channel = RTCDataChannel(id=self.stream_id, label=label, protocol=protocol,
                                 manager=self)
        self.channels[channel.id] = channel
        self.stream_id += 2

        # open channel
        data = pack('!BBHLHH', DATA_CHANNEL_OPEN, DATA_CHANNEL_RELIABLE,
                    0, 0, len(label), len(protocol))
        data += label.encode('utf8')
        data += protocol.encode('utf8')
        asyncio.ensure_future(self.endpoint.send(channel.id, WEBRTC_DCEP, data))

        return channel

    def send(self, channel, data):
        if data == '':
            asyncio.ensure_future(self.endpoint.send(channel.id, WEBRTC_STRING_EMPTY, b'\x00'))
        elif isinstance(data, str):
            asyncio.ensure_future(self.endpoint.send(channel.id, WEBRTC_STRING,
                                                     data.encode('utf8')))
        elif data == b'':
            asyncio.ensure_future(self.endpoint.send(channel.id, WEBRTC_BINARY_EMPTY, b'\x00'))
        elif isinstance(data, bytes):
            asyncio.ensure_future(self.endpoint.send(channel.id, WEBRTC_BINARY, data))
        else:
            raise ValueError('Cannot send unsupported data type: %s' % type(data))

    async def run(self, endpoint):
        self.endpoint = endpoint
        while True:
            stream_id, pp_id, data = await self.endpoint.recv()
            if pp_id == WEBRTC_DCEP and len(data):
                msg_type = unpack('!B', data[0:1])[0]
                if msg_type == DATA_CHANNEL_OPEN and len(data) >= 12:
                    # one side should be using even IDs, the other odd IDs
                    assert (stream_id % 2) != (self.stream_id % 2)
                    assert stream_id not in self.channels

                    (msg_type, channel_type, priority, reliability,
                     label_length, protocol_length) = unpack('!BBHLHH', data[0:12])
                    pos = 12
                    label = data[pos:pos + label_length].decode('utf8')
                    pos += label_length
                    protocol = data[pos:pos + protocol_length].decode('utf8')

                    # register channel
                    channel = RTCDataChannel(id=stream_id, label=label, protocol=protocol,
                                             manager=self)
                    self.channels[stream_id] = channel

                    # send ack
                    await self.endpoint.send(channel.id, WEBRTC_DCEP, pack('!B', DATA_CHANNEL_ACK))

                    # emit channel
                    self.pc.emit('datachannel', channel)
                elif msg_type == DATA_CHANNEL_ACK:
                    pass
            elif pp_id == WEBRTC_STRING and stream_id in self.channels:
                # emit message
                self.channels[stream_id].emit('message', data.decode('utf8'))
            elif pp_id == WEBRTC_STRING_EMPTY and stream_id in self.channels:
                # emit message
                self.channels[stream_id].emit('message', '')
            elif pp_id == WEBRTC_BINARY and stream_id in self.channels:
                # emit message
                self.channels[stream_id].emit('message', data)
            elif pp_id == WEBRTC_BINARY_EMPTY and stream_id in self.channels:
                # emit message
                self.channels[stream_id].emit('message', b'')


class RTCDataChannel(EventEmitter):
    def __init__(self, id, label, protocol, manager, loop=None):
        super().__init__(loop=loop)
        self.__id = id
        self.__label = label
        self.__manager = manager
        self.__protocol = protocol

    def close(self):
        pass

    def send(self, data):
        self.__manager.send(self, data)

    @property
    def id(self):
        """
        An ID number which uniquely identifies the data channel.
        """
        return self.__id

    @property
    def label(self):
        """
        A name describing the data channel.

        These labels are not required to be unique.
        """
        return self.__label

    @property
    def protocol(self):
        """
        The name of the subprotocol in use.
        """
        return self.__protocol

{'fraction_non_alphanumeric': 0.09426013691416535, 'fraction_numerical': 0.00842548709847288, 'mean_word_length': 1.8593797049081602, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1177785', 'n_tokens_mistral': 2731, 'n_tokens_neox': 2552, 'n_words': 640}