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; } }
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; } }
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()); }
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(); } }
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(); } }
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; }
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()); }
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 }
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; } }
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; }
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; }
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; }
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; } }
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); }
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; } } } }
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); } }
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; } } } }
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; } } } }
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); }
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); } } }
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; }
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); } } }
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; }
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; } }
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); } }