예제 #1
0
void CDPlusHandler::writeAMBEInt(IReflectorCallback* handler, CAMBEData& data, DIRECTION direction)
{
	if (m_linkState != DPLUS_LINKED)
		return;

	if (direction != m_direction)
		return;

	// Already in use?
	if (m_dPlusId != 0x00U)
		return;

	switch (m_direction) {
		case DIR_OUTGOING:
			if (m_destination == handler) {
				data.setDestination(m_yourAddress, m_yourPort);
				m_handler->writeAMBE(data);
			}
			break;

		case DIR_INCOMING:
			data.setDestination(m_yourAddress, m_yourPort);
			m_handler->writeAMBE(data);
			break;
	}
}
예제 #2
0
void CDPlusHandler::writeAMBEInt(CAMBEData& data, DIRECTION direction)
{
	if (m_linkState != DPLUS_LINKED)
		return;

	if (direction != m_direction)
		return;

	// Already in use?
	if (m_dPlusId != 0x00U)
		return;

	switch (m_direction) {
		case DIR_OUTGOING:
			if (data.getId() == m_rptrId) {
				data.setDestination(m_yourAddress, m_yourPort);
				m_handler->writeAMBE(data);

				if (data.isEnd())
					m_rptrId = 0x00U;
			}
			break;

		case DIR_INCOMING:
			data.setDestination(m_yourAddress, m_yourPort);
			m_handler->writeAMBE(data);
			break;
	}
}
예제 #3
0
bool CAPRSTransmit::sendData(const CAMBEData& data)
{
	unsigned char buffer[60U];
	unsigned int length = data.getG2Data(buffer, 60U);

	return m_socket.write(buffer, length, data.getYourAddress(), data.getYourPort());
}
예제 #4
0
void CDPlusHandler::processInt(CAMBEData& data)
{
	unsigned int id = data.getId();

	if (m_dPlusId != id)
		return;

	m_dPlusSeq = data.getSeq();

	// Send the header every 21 frames
	if (m_dPlusSeq == 0U)
		m_destination->process(*m_header, AS_DUP);

	m_inactivityTimer.reset();
	m_pollInactivityTimer.reset();

	m_destination->process(data, AS_DPLUS);

	if (data.isEnd()) {
		m_dPlusId  = 0x00U;
		m_dPlusSeq = 0x00U;

		delete m_header;
		m_header = NULL;

		m_inactivityTimer.stop();
	}
}
예제 #5
0
void CDExtraHandler::processInt(CAMBEData& data)
{
	if (m_linkState != DEXTRA_LINKED)
		return;

	if (m_dExtraId != data.getId())
		return;

	m_inactivityTimer.reset();

	m_dExtraSeq = data.getSeq();

	// Send the header every 21 frames
	if (m_dExtraSeq == 0U)
		m_destination->process(*m_header, AS_DUP);

	// Copy the data to ensure it remains unchanged
	CAMBEData temp(data);

	m_destination->process(temp, AS_DEXTRA);

	if (temp.isEnd()) {
		delete m_header;
		m_header = NULL;

		m_dExtraId  = 0x00U;
		m_dExtraSeq = 0x00U;

		m_inactivityTimer.stop();
	}
}
예제 #6
0
void CG2Handler::process(CAMBEData& data)
{
	// Check to see if this is for StarNet
	CStarNetHandler* handler = CStarNetHandler::findStarNet(data);
	if (handler != NULL) {
		handler->process(data);
		return;
	}

	// No need to go any further
	if (m_maxRoutes == 0U)
		return;

	unsigned int id = data.getId();

	for (unsigned int i = 0U; i < m_maxRoutes; i++) {
		CG2Handler* route = m_routes[i];
		if (route != NULL) {
			if (route->m_id == id) {
				route->m_inactivityTimer.reset();
				route->m_repeater->process(data, DIR_INCOMING, AS_G2);

				if (data.isEnd()) {
					delete route;
					m_routes[i] = NULL;
				}

				return;
			}
		}
	}	
}
bool CTimeServerThread::lookup(const wxString &id)
{
	CIndexRecord* info = m_index[id];
	if (info == NULL) {
		// wxLogError(wxT("Cannot find the AMBE index for *%s*"), id.c_str());
		return false;
	}

	unsigned int  start = info->getStart();
	unsigned int length = info->getLength();

	SLOW_DATA slowData = SD_TEXT;

	for (unsigned int i = 0U; i < length; i++) {
		unsigned char* dataIn = m_ambe + (start + i) * VOICE_FRAME_LENGTH_BYTES;

		CAMBEData* dataOut = new CAMBEData;
		dataOut->setDestination(m_address, G2_DV_PORT);
		dataOut->setSeq(m_seqNo);

		unsigned char buffer[DV_FRAME_LENGTH_BYTES];
		::memcpy(buffer + 0U, dataIn, VOICE_FRAME_LENGTH_BYTES);

		// Insert sync bytes when the sequence number is zero, slow data otherwise
		if (m_seqNo == 0U) {
			::memcpy(buffer + VOICE_FRAME_LENGTH_BYTES, DATA_SYNC_BYTES, DATA_FRAME_LENGTH_BYTES);
			m_encoder.sync();

			switch (slowData) {
				case SD_HEADER:
					slowData = SD_TEXT;
					break;
				case SD_TEXT:
					slowData = SD_HEADER;
					break;
			}
		} else {
			switch (slowData) {
				case SD_HEADER:
					m_encoder.getHeaderData(buffer + VOICE_FRAME_LENGTH_BYTES);
					break;
				case SD_TEXT:
					m_encoder.getTextData(buffer + VOICE_FRAME_LENGTH_BYTES);
					break;
			}
		}

		dataOut->setData(buffer, DV_FRAME_LENGTH_BYTES);

		m_seqNo++;
		if (m_seqNo == 21U)
			m_seqNo = 0U;

		m_data[m_in] = dataOut;
		m_in++;
	}

	return true;
}
예제 #8
0
bool CCCSProtocolHandler::writeData(const CAMBEData& data)
{
	unsigned char buffer[100U];
	unsigned int length = data.getCCSData(buffer, 100U);

#if defined(DUMP_TX)
	CUtils::dump(wxT("Sending Data"), buffer, length);
#endif

	return m_socket.write(buffer, length, data.getYourAddress(), data.getYourPort());
}
예제 #9
0
void CDExtraHandler::process(CAMBEData& data)
{
	for (unsigned int i = 0U; i < m_maxReflectors; i++) {
		CDExtraHandler* reflector = m_reflectors[i];
		if (reflector != NULL) {
			if (reflector->m_address.s_addr == data.getAddress().s_addr &&
				reflector->m_port           == data.getPort())
				reflector->processInt(data);
		}
	}	
}
void CTimeServerThread::end()
{
	CAMBEData* dataOut = new CAMBEData;
	dataOut->setData(END_PATTERN_BYTES, DV_FRAME_LENGTH_BYTES);
	dataOut->setDestination(m_address, G2_DV_PORT);
	dataOut->setSeq(m_seqNo);
	dataOut->setEnd(true);

	m_data[m_in] = dataOut;
	m_in++;
}
bool CTimeServerThread::sendData(const CAMBEData& data)
{
	unsigned char buffer[40U];
	unsigned int length = data.getG2Data(buffer, 40U);

#if defined(DUMP_TX)
	CUtils::dump(wxT("Sending Data"), buffer, length);
	return true;
#else
	return m_socket.write(buffer, length, data.getAddress(), data.getPort());
#endif
}
bool CHBRepeaterProtocolHandler::writeAMBE(CAMBEData& data)
{
	unsigned char buffer[30U];
	unsigned int length = data.getHBRepeaterData(buffer, 30U);

#if defined(DUMP_TX)
	CUtils::dump(wxT("Sending Data"), buffer, length);
	return true;
#else
	return m_socket.write(buffer, length, data.getYourAddress(), data.getYourPort());
#endif
}
예제 #13
0
void CEchoUnit::clock(unsigned int ms)
{
    m_timer.clock(ms);

    if (m_status == ES_WAIT && m_timer.hasExpired()) {
        m_timer.stop();

        // RPT1 and RPT2 will be filled in later
        m_header->setMyCall1(m_callsign);
        m_header->setMyCall2(wxT("ECHO"));
        m_header->setYourCall(wxT("CQCQCQ  "));

        m_handler->process(*m_header, AS_ECHO);

        delete m_header;

        m_out    = 0U;
        m_status = ES_TRANSMIT;

        m_time.Start();

        return;
    }

    if (m_status == ES_TRANSMIT) {
        unsigned int needed = m_time.Time() / DSTAR_FRAME_TIME_MS;

        while (m_out < needed) {
            CAMBEData* data = m_data[m_out];
            m_data[m_out] = NULL;
            m_out++;

            if (m_in == m_out)
                data->setEnd(true);

            m_handler->process(*data, AS_ECHO);

            delete data;

            if (m_in == m_out) {
                m_in     = 0U;
                m_out    = 0U;
                m_status = ES_IDLE;
                return;
            }
        }

        return;
    }
}
예제 #14
0
CAMBEData* CDPlusProtocolHandler::readAMBE()
{
	if (m_type != DP_AMBE)
		return NULL;

	CAMBEData* data = new CAMBEData;

	bool res = data->setDPlusData(m_buffer, m_length, m_yourAddress, m_yourPort, m_myPort);
	if (!res) {
		delete data;
		return NULL;
	}

	return data;
}
예제 #15
0
CAMBEData* CCCSProtocolHandler::readData()
{
	if (m_type != CT_DATA)
		return NULL;

	CAMBEData* data = new CAMBEData;

	bool res = data->setCCSData(m_buffer, m_length, m_yourAddress, m_yourPort, m_myPort);
	if (!res) {
		delete data;
		return NULL;
	}

	return data;
}
예제 #16
0
void CXReflectorDPlusHandler::processInt(CAMBEData& data)
{
    unsigned int id = data.getId();

    if (m_dPlusId == id) {
        m_inactivityTimer.reset();
        m_pollInactivityTimer.reset();
        m_destination->process(m_dPlusId, data);

        if (data.isEnd()) {
            m_dPlusId = 0x00;
            m_inactivityTimer.stop();
        }
    }
}
CAMBEData* CHBRepeaterProtocolHandler::readBusyAMBE()
{
	if (m_type != RT_BUSY_AMBE)
		return NULL;

	CAMBEData* data = new CAMBEData;

	bool res = data->setHBRepeaterData(m_buffer, m_length, m_address, m_port);
	if (!res) {
		wxLogError(wxT("Invalid AMBE data from the repeater"));
		delete data;
		return NULL;
	}

	return data;
}
예제 #18
0
void CVersionUnit::clock(unsigned int ms)
{
	m_timer.clock(ms);

	if (m_status == VS_WAIT && m_timer.hasExpired()) {
		m_timer.stop();

		// RPT1 and RPT2 will be filled in later
		CHeaderData header;
		header.setMyCall1(m_callsign);
		header.setMyCall2(wxT("VERS"));
		header.setYourCall(wxT("CQCQCQ  "));
		header.setId(m_id);

		m_handler->process(header, DIR_INCOMING, AS_VERSION);

		m_out    = 0U;
		m_status = VS_TRANSMIT;

		m_time.Start();

		return;
	}

	if (m_status == VS_TRANSMIT) {
		unsigned int needed = m_time.Time() / DSTAR_FRAME_TIME_MS;

		while (m_out < needed) {
			CAMBEData* data = m_data[m_out];
			data->setId(m_id);

			m_out++;

			m_handler->process(*data, DIR_INCOMING, AS_VERSION);

			if (m_out == NUM_FRAMES) {
				m_out    = 0U;
				m_status = VS_IDLE;
				return;
			}
		}

		return;
	}
}
예제 #19
0
void CCCSHandler::process(CAMBEData& data)
{
	CHeaderData& header = data.getHeader();
	unsigned int seqNo = data.getSeq();
	unsigned int id = data.getId();

	if (m_state != CS_CONNECTED && m_state != CS_ACTIVE)
		return;

	// This is a new incoming CCS call
	if (m_state == CS_CONNECTED) {
		m_yourCall    = header.getMyCall1();
		m_local       = header.getYourCall();
		m_direction   = DIR_INCOMING;
		m_time        = ::time(NULL);
		m_state       = CS_ACTIVE;
		m_stateChange = true;
		m_inactivityTimer.start();

		m_handler->ccsLinkMade(m_yourCall);

		wxLogMessage(wxT("CCS: New incoming link to %s from %s"), m_local.c_str(), m_yourCall.c_str());
	}

	m_pollInactivityTimer.reset();
	m_inactivityTimer.reset();

	if (m_id != id) {
		// Write to Header.log if it's enabled
		if (m_headerLogger != NULL)
			m_headerLogger->write(wxT("CCS"), header);

		header.setCQCQCQ();
		m_handler->process(header, DIR_INCOMING, AS_CCS);

		m_id = id;
	} else if (seqNo == 0U) {
		header.setCQCQCQ();
		m_handler->process(header, DIR_INCOMING, AS_DUP);
	}

	m_handler->process(data, DIR_INCOMING, AS_CCS);
}
예제 #20
0
void CDPlusHandler::process(CAMBEData& data)
{
	in_addr   yourAddress = data.getYourAddress();
	unsigned int yourPort = data.getYourPort();
	unsigned int   myPort = data.getMyPort();

	for (unsigned int i = 0U; i < m_maxReflectors; i++) {
		CDPlusHandler* reflector = m_reflectors[i];

		if (reflector != NULL) {
			if (reflector->m_yourAddress.s_addr == yourAddress.s_addr &&
				reflector->m_yourPort           == yourPort &&
				reflector->m_myPort             == myPort) {
				reflector->processInt(data);
				return;
			}
		}
	}	
}
예제 #21
0
void CStarNetHandler::sendAck(const CUserData& user, const wxString& text) const
{
	unsigned int id = CHeaderData::createId();

	CHeaderData header(m_groupCallsign, wxT("    "), user.getUser(), user.getGateway(), user.getRepeater());
	header.setDestination(user.getAddress(), G2_DV_PORT);
	header.setId(id);
	m_g2Handler->writeHeader(header);

	CSlowDataEncoder slowData;
	slowData.setTextData(text);

	CAMBEData data;
	data.setId(id);
	data.setDestination(user.getAddress(), G2_DV_PORT);

	unsigned char buffer[DV_FRAME_MAX_LENGTH_BYTES];
	::memcpy(buffer + 0U, NULL_AMBE_DATA_BYTES, VOICE_FRAME_LENGTH_BYTES);

	for (unsigned int i = 0U; i < 20U; i++) {
		if (i == 0U) {
			// The first AMBE packet is a sync
			::memcpy(buffer + VOICE_FRAME_LENGTH_BYTES, DATA_SYNC_BYTES, DATA_FRAME_LENGTH_BYTES);
			data.setData(buffer, DV_FRAME_LENGTH_BYTES);
			data.setSeq(i);
		} else if (i == 19U) {
			// The last packet of the ack
			::memcpy(buffer + VOICE_FRAME_LENGTH_BYTES, END_PATTERN_BYTES, END_PATTERN_LENGTH_BYTES);
			data.setData(buffer, DV_FRAME_MAX_LENGTH_BYTES);
			data.setSeq(i);
			data.setEnd(true);
		} else {
			// The packets containing the text data
			unsigned char slowDataBuffer[DATA_FRAME_LENGTH_BYTES];
			slowData.getTextData(slowDataBuffer);
			::memcpy(buffer + VOICE_FRAME_LENGTH_BYTES, slowDataBuffer, DATA_FRAME_LENGTH_BYTES);
			data.setData(buffer, DV_FRAME_LENGTH_BYTES);
			data.setSeq(i);
		}

		m_g2Handler->writeAMBE(data);
	}
}
예제 #22
0
void CDPlusHandler::unlink(IReflectorCallback* handler, const wxString& exclude)
{
	for (unsigned int i = 0U; i < m_maxReflectors; i++) {
		CDPlusHandler* reflector = m_reflectors[i];

		if (reflector != NULL) {
			if (reflector->m_direction == DIR_OUTGOING && reflector->m_destination == handler && !reflector->m_reflector.IsSameAs(exclude)) {
				wxLogMessage(wxT("Removing outgoing D-Plus link %s, %s"), reflector->m_repeater.c_str(), reflector->m_reflector.c_str());

				if (reflector->m_linkState == DPLUS_LINKING || reflector->m_linkState == DPLUS_LINKED) {
					CConnectData connect(CT_UNLINK, reflector->m_yourAddress, DPLUS_PORT);
					reflector->m_handler->writeConnect(connect);
					reflector->m_handler->writeConnect(connect);

					reflector->m_linkState = DPLUS_UNLINKING;
					reflector->m_tryTimer.setTimeout(1U);
					reflector->m_tryTimer.start();
					reflector->m_pollTimer.stop();
					reflector->m_pollInactivityTimer.stop();
					reflector->m_tryCount = 0U;
				}

				// If an active link with incoming traffic, send an EOT to the repeater
				if (reflector->m_dPlusId != 0x00U) {
					unsigned int seq = reflector->m_dPlusSeq + 1U;
					if (seq == 21U)
						seq = 0U;

					CAMBEData data;
					data.setData(END_PATTERN_BYTES, DV_FRAME_LENGTH_BYTES);
					data.setSeq(seq);
					data.setEnd(true);
					data.setId(reflector->m_dPlusId);

					reflector->m_destination->process(data, AS_DPLUS);
				}

				m_stateChange = true;
			}
		}
	}
}
예제 #23
0
void CDExtraHandler::unlink(IReflectorCallback* handler, const wxString& exclude)
{
	for (unsigned int i = 0U; i < m_maxReflectors; i++) {
		CDExtraHandler* reflector = m_reflectors[i];

		if (reflector != NULL) {
			if (reflector->m_direction == DIR_OUTGOING && reflector->m_destination == handler && !reflector->m_reflector.IsSameAs(exclude)) {
				wxLogMessage(wxT("Removing outgoing DExtra link %s, %s"), reflector->m_repeater.c_str(), reflector->m_reflector.c_str());

				if (reflector->m_linkState == DEXTRA_LINKING || reflector->m_linkState == DEXTRA_LINKED) {
					CConnectData connect(reflector->m_repeater, reflector->m_address, reflector->m_port);
					m_handler->writeConnect(connect);

					reflector->m_linkState = DEXTRA_UNLINKING;

					reflector->m_destination->linkDown(DP_DEXTRA, reflector->m_reflector, false);
				}

				// If an active link with incoming traffic, send an EOT to the repeater
				if (reflector->m_dExtraId != 0x00U) {
					unsigned int seq = reflector->m_dExtraSeq + 1U;
					if (seq == 21U)
						seq = 0U;

					CAMBEData data;
					data.setData(END_PATTERN_BYTES, DV_FRAME_LENGTH_BYTES);
					data.setSeq(seq);
					data.setEnd(true);
					data.setId(reflector->m_dExtraId);

					reflector->m_destination->process(data, AS_DEXTRA);
				}

				m_stateChange = true;

				delete m_reflectors[i];
				m_reflectors[i] = NULL;
			}
		}
	}	
}
예제 #24
0
void CXReflectorDPlusHandler::writeAMBEInt(CAMBEData& data)
{
    if (!m_linked)
        return;

    // If there's an incoming data stream, don't send
    if (m_dPlusId != 0x00U)
        return;

    data.setDestination(m_address, m_port);
    m_handler->writeAMBE(data);
}
예제 #25
0
void CDPlusHandler::process(CAMBEData& data)
{
    in_addr address = data.getAddress();

    for (unsigned int i = 0U; i < m_maxReflectors; i++) {
        CDPlusHandler* reflector = m_reflectors[i];
        if (reflector != NULL) {
            if (reflector->m_address.s_addr == address.s_addr)
                reflector->processInt(data);
        }
    }
}
예제 #26
0
bool CStarNetHandler::process(CAMBEData &data, AUDIO_SOURCE source)
{
	unsigned int id = data.getId();
	if (id != m_id)
		return false;

	m_linkTimer.reset();

	sendToRepeaters(data);

	if (data.isEnd()) {
		m_linkTimer.stop();
		m_id = 0x00U;

		// Clear the repeater list
		for (CStarNetRepeatersHashMap::iterator it = m_repeaters.begin(); it != m_repeaters.end(); ++it)
			delete it->second;
		m_repeaters.clear();
	}

	return true;
}
예제 #27
0
void CStarNetHandler::sendToRepeaters(CAMBEData& data) const
{
	for (CStarNetRepeatersHashMap::const_iterator it = m_repeaters.begin(); it != m_repeaters.end(); ++it) {
		CStarNetRepeater* repeater = it->second;
		if (repeater != NULL) {
			data.setDestination(repeater->m_address, G2_DV_PORT);
			if (repeater->m_local != NULL)
				repeater->m_local->process(data, AS_G2);
			else
				m_g2Handler->writeAMBE(data);
		}
	}
}
예제 #28
0
void CDExtraHandler::writeAMBEInt(CAMBEData& data, DIRECTION direction)
{
	if (m_linkState != DEXTRA_LINKED)
		return;

	// Is it link in the right direction
	if (m_direction != direction)
		return;

	// If the ids don't match, reject
	if (data.getId() != m_rptrId)
		return;

	// Already in use?
	if (m_dExtraId != 0x00)
		return;

	data.setDestination(m_address, m_port);
	m_handler->writeAMBE(data);

	if (data.isEnd())
		m_rptrId = 0x00;
}
예제 #29
0
void CEchoUnit::writeData(const CAMBEData& data)
{
    if (m_status != ES_RECEIVE)
        return;

    if (m_in < MAX_FRAMES) {
        m_data[m_in] = new CAMBEData(data);
        m_in++;
    }

    if (data.isEnd()) {
        wxLogMessage(wxT("Received %.1f secs of audio from %s for echoing"), float(m_in) / float(DSTAR_FRAMES_PER_SEC), m_header->getMyCall1().c_str());

        m_timer.start();
        m_status = ES_WAIT;
    }
}
예제 #30
0
void CStarNetHandler::sendFromText(const wxString& my) const
{
	wxString text;
	switch (m_callsignSwitch) {
		case SCS_GROUP_CALLSIGN:
			text.Printf(wxT("FROM %s"), my.c_str());
			break;
		case SCS_USER_CALLSIGN:
			text.Printf(wxT("VIA STARnet %s"), m_groupCallsign.c_str());
			break;
		default:
			break;
	}

	CSlowDataEncoder slowData;
	slowData.setTextData(text);

	CAMBEData data;
	data.setId(m_id);

	unsigned char buffer[DV_FRAME_LENGTH_BYTES];
	::memcpy(buffer + 0U, NULL_AMBE_DATA_BYTES, VOICE_FRAME_LENGTH_BYTES);

	for (unsigned int i = 0U; i < 21U; i++) {
		if (i == 0U) {
			// The first AMBE packet is a sync
			::memcpy(buffer + VOICE_FRAME_LENGTH_BYTES, DATA_SYNC_BYTES, DATA_FRAME_LENGTH_BYTES);
			data.setData(buffer, DV_FRAME_LENGTH_BYTES);
			data.setSeq(i);
		} else {
			// The packets containing the text data
			unsigned char slowDataBuffer[DATA_FRAME_LENGTH_BYTES];
			slowData.getTextData(slowDataBuffer);
			::memcpy(buffer + VOICE_FRAME_LENGTH_BYTES, slowDataBuffer, DATA_FRAME_LENGTH_BYTES);
			data.setData(buffer, DV_FRAME_LENGTH_BYTES);
			data.setSeq(i);
		}

		sendToRepeaters(data);
	}
}