Beispiel #1
0
    def generate_voice_header(self, _rx_slot, _burst_type):
        src_id = struct.pack('>I', int_id(_rx_slot.src_id))
        dst_id = struct.pack('>I', int_id(_rx_slot.dst_id))

        headerType = ord(LC_GROUP_VOICE)
        if not _rx_slot.group:
            headerType = ord(LC_PRIVATE_VOICE)
        if _rx_slot.secure:
            headerType &= ~(1 << 7)

        featureSet = FID_ETSI
        svcOptions = 0x00
        if _rx_slot.secure:
            featureSet = FID_DMRA
            svcOptions &= ~(1 << 6)

        header = struct.pack('B', headerType) + featureSet + struct.pack('B', svcOptions) + \
            dst_id[1] + dst_id[2] + dst_id[3] + src_id[1] + src_id[2] + src_id[3]
        self.emb_lc = header

        fec = ''
        if _burst_type == BURST_DATA_TYPE['VOICE_HEADER']:
            fec = rs129.lc_header_encode(header)
        else:
            fec = rs129.lc_terminator_encode(header)

        ipsc_burst = self.generate_ipsc_burst(_rx_slot, _burst_type)

        burst_type = map(ord, _burst_type)[0]
        burst_type = burst_type + (_rx_slot.cc << 4)
        burst_type = struct.pack('>H', burst_type)
        rssi = struct.pack('>H', 0)  # fake RSSI

        return ipsc_burst + header + fec + burst_type + rssi
Beispiel #2
0
    def begin_call(self, _slot, _group_call, _src_id, _dst_id, _peer_id, _cc,
                   _seq, _stream_id):
        group = '\x01'
        if (_group_call == False):
            group = '\x00'

        metadata = _src_id[0:3] + _peer_id[0:4] + _dst_id[0:3] + struct.pack(
            'B', _slot) + struct.pack('B', _cc) + group

        # start transmission
        self.send_tlv(TAG_BEGIN_TX, metadata)

        self._logger.info(
            'Voice Transmission Start; slot = {}, dstId = {}, srcId = {}'.
            format(_slot, int_id(_dst_id), int_id(_src_id)))

        _tx_slot = self.tx[_slot]
        _tx_slot.slot = _slot
        _tx_slot.src_id = _src_id
        _tx_slot.peer_id = _peer_id
        _tx_slot.dst_id = _dst_id
        _tx_slot.cc = _cc
        _tx_slot.stream_id = _stream_id

        _tx_slot.start_time = time()
        _tx_slot.frame_count = 0
        _tx_slot.lostFrame = 0
        _tx_slot.lastSeq = _seq
Beispiel #3
0
    def pi_params(self, _slot, _dst_id, _alg_id, _key_id, _mi):
        metadata = _dst_id[0:3] + _alg_id + _key_id + _mi[0:4] + struct.pack(
            'B', _slot)

        sleep(0.06)

        # start transmission
        self.send_tlv(TAG_PI_INFO, metadata)

        self._logger.info(
            'PI parameters; slot = {}, dstId = {}, algId = {}, kId = {}'.
            format(_slot, int_id(_dst_id), int_id(_alg_id), int_id(_key_id)))

        _tx_slot = self.tx[_slot]
        _tx_slot.secure = True
        _tx_slot.alg_id = _alg_id
        _tx_slot.key_id = _key_id
        _tx_slot.mi = _mi
Beispiel #4
0
    def send_system(self, _rx_slot, _frame):
        if hasattr(self._parent, '_peers'):
            _orig_flag = _frame[
                15]  # Save off the flag since _frame is a reference
            for _peer in self._parent._peers:
                _peerDict = self._parent._peers[_peer]
                if _peerDict['TX_FREQ'] == _peerDict['RX_FREQ']:
                    if (self._DMOStreamID == 0) or (
                            time() > self._DMOTimeout):  # are we idle?
                        self._DMOStreamID = _rx_slot.stream_id
                        self._DMOTimeout = time() + 0.50
                        self._logger.info(
                            '(%s) DMO Transition from idle to stream %d',
                            self._system, int_id(_rx_slot.stream_id))
                    if _rx_slot.stream_id != self._DMOStreamID:  # packet is from wrong stream?
                        if (_frame[15] & 0x2F) == 0x21:  # Call start?
                            self._logger.info(
                                '(%s) DMO Ignore traffic on stream %d',
                                self._system, int_id(_rx_slot.stream_id))
                        continue
                    if (_frame[15] & 0x2F) == 0x22:  # call terminator flag?
                        self._DMOStreamID = 0  # we are idle again
                        self._logger.info('(%s) DMO End of call, back to IDLE',
                                          self._system)

                    _frame[15] = (
                        _frame[15]
                        & 0x7f) | 0x80  # force to slot 2 if client in DMO mode
                else:
                    _frame[
                        15] = _orig_flag  # Use the origional flag value if not DMO

                _repeaterID = hex_str_4(int(_peerDict['PEER_ID']))
                for _index in range(
                        0, 4
                ):  # Force the repeater ID to be the "destination" ID of the client (fne will not accept it otherwise)
                    _frame[_index + 11] = _repeaterID[_index]

                self._parent.send_peer(_peer, _frame)
                self._DMOTimeout = time() + 0.50
        else:
            self._parent.send_master(_frame)
Beispiel #5
0
    def generate_ipsc_voice_header(self, _rx_slot):
        src_id = struct.pack('>I', int_id(_rx_slot.src_id))
        dst_id = struct.pack('>I', int_id(_rx_slot.dst_id))

        frameType = GROUP_VOICE
        if not _rx_slot.group:
            frameType = PVT_VOICE

        control = 0x00
        if _rx_slot.slot == 1:
            control &= ~(1 << 5)
        elif _rx_slot.slot == 2:
            control |= 1 << 5
        if _rx_slot.secure:
            control &= ~(1 << 7)
        control = chr(control)

        frame = frameType + struct.pack('>I', int_id(_rx_slot.peer_id)) + struct.pack("i", self.ipsc_seq)[0] + \
            src_id[1] + src_id[2] + src_id[3] + dst_id[1] + dst_id[2] + dst_id[3] + \
            CALL_PRIORITY_2 + struct.pack('>I', int_id(_rx_slot.stream_id)) + control

        return frame
Beispiel #6
0
    def voice_call(self, _src_id, _dst_id, _group, _ts, _end, _peerId, _rtp,
                   _data):
        _tx_slot = self.tlv_ipsc.tx[_ts]
        _payload_type = _data[30:31]
        _seq = int_id(_data[20:22])
        _tx_slot.frame_count += 1

        if _payload_type == BURST_DATA_TYPE['VOICE_HEADER']:
            _stream_id = int_id(
                _data[5:6])  # int8  looks like a sequence number for a packet
            if (_stream_id != _tx_slot.stream_id):
                self.tlv_ipsc.begin_call(_ts, _group, _src_id, _dst_id,
                                         _peerId, self.cc, _seq, _stream_id)
            _tx_slot.lastSeq = _seq

        if _payload_type == BURST_DATA_TYPE['PI_HEADER']:
            _stream_id = int_id(
                _data[5:6])  # int8  looks like a sequence number for a packet
            _alg_id = _data[38:39]
            _key_id = _data[40:41]
            _mi = _data[41:45]
            if (_stream_id == _tx_slot.stream_id):
                self.tlv_ipsc.pi_params(_ts, _dst_id, _alg_id, _key_id, _mi)

        if _payload_type == BURST_DATA_TYPE['VOICE_TERMINATOR']:
            self.tlv_ipsc.end_call(_tx_slot)

        if (_payload_type == BURST_DATA_TYPE['SLOT1_VOICE']) or (
                _payload_type == BURST_DATA_TYPE['SLOT2_VOICE']):
            _ambe_frames = BitArray('0x' + ahex(_data[33:52]))
            _ambe_frame1 = _ambe_frames[0:49]
            _ambe_frame2 = _ambe_frames[50:99]
            _ambe_frame3 = _ambe_frames[100:149]
            self.tlv_ipsc.export_voice(
                _tx_slot, _seq,
                _ambe_frame1.tobytes() + _ambe_frame2.tobytes() +
                _ambe_frame3.tobytes())
Beispiel #7
0
    def generate_pi_header(self, _rx_slot, _burst_type):
        _unk = '\x00'

        dst_id = struct.pack('>I', int_id(_rx_slot.dst_id))

        featureSet = FID_DMRA

        header = struct.pack('B', _rx_slot.alg_id) + featureSet + struct.pack('B', _rx_slot.key_id) + \
            mi[0] + mi[1] + mi[2] + mi[3] + dst_id[1] + dst_id[2] + dst_id[3] + _unk + _unk

        ipsc_burst = self.generate_ipsc_burst(_rx_slot, _burst_type)

        burst_type = map(ord, _burst_type)[0]
        burst_type = burst_type + (_rx_slot.cc << 4)
        burst_type = struct.pack('>H', burst_type)
        rssi = struct.pack('>H', 0)  # fake RSSI

        return ipsc_burst + header + fec + burst_type + rssi
Beispiel #8
0
    def dmrd_received(self, _peer_id, _rf_src, _dst_id, _seq, _slot,
                      _call_type, _frame_type, _dtype_vseq, _stream_id, _data):
        dmrpkt = _data[20:53]
        _tx_slot = self.tlv_fne.tx[_slot]
        _seq = ord(_data[4])
        _tx_slot.frame_count += 1

        if (_stream_id != _tx_slot.stream_id):
            if _call_type == 'group':
                self.tlv_fne.begin_call(_slot, True, _rf_src, _dst_id,
                                        _peer_id, _tx_slot.cc, _seq,
                                        _stream_id)
            elif _call_type == 'unit':
                self.tlv_fne.begin_call(_slot, False, _rf_src, _dst_id,
                                        _peer_id, _tx_slot.cc, _seq,
                                        _stream_id)
            _tx_slot.lastSeq = _seq

        if (_frame_type == fne_const.FT_DATA_SYNC) and (
                _dtype_vseq == fne_const.DT_VOICE_PI_HEADER):
            lcHeader = lc.decode_lc_header(dmrpkt)
            _alg_id = lcHeader['LC'][0]
            _key_id = lcHeader['LC'][2]
            _mi = lcHeader['LC'][3:7]
            self.tlv_fne.pi_params(_slot, _dst_id, _alg_id, _key_id, _mi)

        if (_frame_type == fne_const.FT_DATA_SYNC) and (
                _dtype_vseq == fne_const.DT_TERMINATOR_WITH_LC) and (
                    _tx_slot.type != fne_const.DT_TERMINATOR_WITH_LC):
            self.tlv_fne.end_call(_tx_slot)

        if (int_id(_data[15]) & 0x20) == 0:
            _dmr_frame = BitArray('0x' + ahex(_data[20:]))
            _ambe = _dmr_frame[0:108] + _dmr_frame[156:264]
            self.tlv_fne.export_voice(_tx_slot, _seq, _ambe.tobytes())
        else:
            _tx_slot.lastSeq = _seq
Beispiel #9
0
    def import_datagramReceived(self, _data, (_host, _port)):
        #self._logger.debug('(%s) Network Received TLV (from %s:%s) -- %s', self._system, _host, _port, ahex(_data))
        _slot = self._slot
        _rx_slot = self.rx[_slot]

        # Parse out the TLV
        t = _data[0]
        if (t):
            l = _data[1]
            if (l):
                v = _data[2:]
                if (v):
                    t = ord(t)
                    if (t == TAG_BEGIN_TX):
                        if ord(l) > 1:
                            _slot = int_id(v[10:11])
                            _rx_slot = self.rx[_slot]
                            _rx_slot.slot = _slot
                            _rx_slot.src_id = hex_str_3(int_id(v[0:3]))
                            _rx_slot.peer_id = self._parent.get_peer_id(
                                hex_str_4(int_id(v[3:7])))
                            _rx_slot.dst_id = hex_str_3(int_id(v[7:10]))
                            _rx_slot.cc = int_id(v[11:12])

                            group = int_id(v[12])
                            if (group == 0):
                                _rx_slot.group = False
                            else:
                                _rx_slot.group = True

                        _rx_slot.stream_id = hex_str_4(randint(
Beispiel #10
0
    def p25d_received(self, _peer_id, _rf_src, _dst_id, _call_type, _duid,
                      _dtype_vseq, _stream_id, _data):
        pkt_time = time()
        p25pkt = _data[24:178]
        _slot = 1  # fake the slot data, P25 doesn't have this

        if _call_type == 'group':
            if (self.LAST_MODE != 'P25'):
                self._logger.info(
                    '(%s) P25D: Previous call was not P25, mixed call modes! Dropping call data.',
                    self._system)
                self.CALL_DATA = []

            if (int_id(_rf_src) == 0):
                self._logger.warning(
                    '(%s) P25D: Received call from SRC_ID %s? Dropping call data.',
                    self._system, int_id(_rf_src))
                self.CALL_DATA = []
                self.LAST_MODE = 'P25'
                return

            self.LAST_MODE = 'P25'

            # Is this is a new call stream?
            if (_stream_id != self.STATUS[_slot]['RX_STREAM_ID']) and (
                (_duid != fne_const.P25_DUID_TDU) and
                (_duid != fne_const.P25_DUID_TDULC)):
                self.STATUS['RX_START'] = pkt_time
                self._logger.info(
                    '(%s) P25D: Traffic *CALL START    * PEER %s SRC_ID %s TGID %s [STREAM ID %s]',
                    self._system, int_id(_peer_id), int_id(_rf_src),
                    int_id(_dst_id), int_id(_stream_id))

            # Final actions - Is this a voice terminator?
            if ((_duid == fne_const.P25_DUID_TDU) or
                (_duid == fne_const.P25_DUID_TDULC)) and (
                    self.STATUS[_slot]['RX_TYPE'] !=
                    fne_const.DT_TERMINATOR_WITH_LC):
                call_duration = pkt_time - self.STATUS['RX_START']
                self._logger.info(
                    '(%s) P25D: Traffic *CALL END      * PEER %s SRC_ID %s TGID %s DUR %s [STREAM ID %s]',
                    self._system, int_id(_peer_id), int_id(_rf_src),
                    int_id(_dst_id), call_duration, int_id(_stream_id))
                self.CALL_DATA.append(_data)
                sleep(2)
                self._logger.info(
                    '(%s) P25D: Playing back transmission from SRC_ID %s',
                    self._system, int_id(_rf_src))
                for _peer in self.CALL_DATA:
                    self.send_peers(_peer)
                    sleep(0.06)
                self.CALL_DATA = []

            else:
                if not self.CALL_DATA:
                    self._logger.info(
                        '(%s) P25D: Receiving transmission to be played back from SRC_ID %s',
                        self._system, int_id(_rf_src))
                self.CALL_DATA.append(_data)

            # Mark status variables for use later
            self.STATUS[_slot]['RX_RFS'] = _rf_src
            self.STATUS[_slot]['RX_TYPE'] = _dtype_vseq
            self.STATUS[_slot]['RX_TGID'] = _dst_id
            self.STATUS[_slot]['RX_TIME'] = pkt_time
            self.STATUS[_slot]['RX_STREAM_ID'] = _stream_id
Beispiel #11
0
    def dmrd_received(self, _peer_id, _rf_src, _dst_id, _seq, _slot,
                      _call_type, _frame_type, _dtype_vseq, _stream_id, _data):
        pkt_time = time()
        dmrpkt = _data[20:53]
        _bits = int_id(_data[15])

        if _call_type == 'group':
            if (self.LAST_MODE != 'DMR'):
                self._logger.info(
                    '(%s) DMRD: Previous call was not DMR, mixed call modes! Dropping call data.',
                    self._system)
                self.CALL_DATA = []

            if (int_id(_rf_src) == 0):
                self._logger.warning(
                    '(%s) DMRD: Received call from SRC_ID %s? Dropping call data.',
                    self._system, int_id(_rf_src))
                self.CALL_DATA = []
                self.LAST_MODE = 'P25'
                return

            self.LAST_MODE = 'DMR'

            # Is this is a new call stream?
            if (_stream_id != self.STATUS[_slot]['RX_STREAM_ID']):
                self.STATUS['RX_START'] = pkt_time
                self._logger.info(
                    '(%s) DMRD: Traffic *CALL START     * PEER %s SRC_ID %s TGID %s TS %s [STREAM ID %s]',
                    self._system, int_id(_peer_id), int_id(_rf_src),
                    int_id(_dst_id), _slot, int_id(_stream_id))

            # Final actions - Is this a voice terminator?
            if (_frame_type == fne_const.FT_DATA_SYNC) and (
                    _dtype_vseq == fne_const.DT_TERMINATOR_WITH_LC) and (
                        self.STATUS[_slot]['RX_TYPE'] !=
                        fne_const.DT_TERMINATOR_WITH_LC):
                call_duration = pkt_time - self.STATUS['RX_START']
                self._logger.info(
                    '(%s) DMRD: Traffic *CALL END       * PEER %s SRC_ID %s TGID %s TS %s DUR %s [STREAM ID %s]',
                    self._system, int_id(_peer_id), int_id(_rf_src),
                    int_id(_dst_id), _slot, call_duration, int_id(_stream_id))
                self.CALL_DATA.append(_data)
                sleep(2)
                self._logger.info(
                    '(%s) DMRD: Playing back transmission from SRC_ID %s',
                    self._system, int_id(_rf_src))
                for _peer in self.CALL_DATA:
                    self.send_peers(_peer)
                    sleep(0.06)
                self.CALL_DATA = []

            else:
                if not self.CALL_DATA:
                    self._logger.info(
                        '(%s) DMRD: Receiving transmission to be played back from SRC_ID %s',
                        self._system, int_id(_rf_src))
                self.CALL_DATA.append(_data)

            # Mark status variables for use later
            self.STATUS[_slot]['RX_RFS'] = _rf_src
            self.STATUS[_slot]['RX_TYPE'] = _dtype_vseq
            self.STATUS[_slot]['RX_TGID'] = _dst_id
            self.STATUS[_slot]['RX_TIME'] = pkt_time
            self.STATUS[_slot]['RX_STREAM_ID'] = _stream_id