bool CDExtraHandler::processInt(CConnectData& connect, CD_TYPE type)
{
	in_addr address   = connect.getAddress();
	unsigned int port = connect.getPort();
	wxString repeater = connect.getRepeater();

	if (m_address.s_addr != address.s_addr || m_port != port)
		return false;

	switch (type) {
		case CT_ACK:
			if (!m_repeater.IsSameAs(repeater))
				return false;

			if (m_linkState == DEXTRA_LINKING) {
				wxLogMessage(wxT("DExtra ACK message received from %s"), m_reflector.c_str());

				if (m_direction == DIR_OUTGOING && m_destination != NULL)
					m_destination->linkUp(DP_DEXTRA, m_reflector);

				m_tryTimer.stop();
				m_pollTimer.start();
				m_stateChange = true;
				m_linkState   = DEXTRA_LINKED;
			}

			return false;

		case CT_NAK:
			if (!m_repeater.IsSameAs(repeater))
				return false;

			if (m_linkState == DEXTRA_LINKING) {
				wxLogMessage(wxT("DExtra NAK message received from %s"), m_reflector.c_str());

				if (m_direction == DIR_OUTGOING && m_destination != NULL)
					m_destination->linkDown(DP_DEXTRA, m_reflector, false);

				return true;
			}

			return false;

		case CT_UNLINK:
			if (!m_reflector.IsSameAs(repeater))
				return false;

			if (m_linkState == DEXTRA_LINKED) {
				wxLogMessage(wxT("DExtra disconnect message received from %s"), m_reflector.c_str());

				if (m_direction == DIR_OUTGOING && m_destination != NULL)
					m_destination->linkDown(DP_DEXTRA, m_reflector, false);

				m_stateChange = true;
			}

			return true;

		default:
			return false;
	}
}
bool CDPlusHandler::processInt(CConnectData& connect, CD_TYPE type)
{
    switch (m_direction) {
    case DIR_OUTGOING:
        switch (type) {
        case CT_ACK:
            if (m_linkState == DPLUS_LINKING) {
                wxLogMessage(wxT("D-Plus ACK message received from %s"), m_reflector.c_str());
                m_destination->linkUp(DP_DPLUS, m_reflector);
                m_stateChange = true;
                m_linkState   = DPLUS_LINKED;
                m_tryTimer.stop();
                m_pollTimer.start();
                m_pollInactivityTimer.start();
            }
            return false;

        case CT_NAK:
            if (m_linkState == DPLUS_LINKING) {
                wxLogMessage(wxT("D-Plus NAK message received from %s"), m_reflector.c_str());
                m_destination->linkDown(DP_DPLUS, m_reflector, false);
                CConnectData reply(CT_UNLINK, connect.getAddress(), connect.getPort());
                m_handler->writeConnect(reply);
                m_tryTimer.stop();
            }
            return true;

        case CT_UNLINK:
            if (m_linkState == DPLUS_UNLINKING) {
                wxLogMessage(wxT("D-Plus disconnect acknowledgement received from %s"), m_reflector.c_str());
                m_destination->linkDown(DP_DPLUS, m_reflector, false);
                m_stateChange = true;
                m_tryTimer.stop();
            }
            return true;

        case CT_LINK1: {
            CConnectData reply(m_dplusLogin, CT_LINK2, connect.getAddress(), connect.getPort());
            m_handler->writeConnect(reply);
            m_tryTimer.stop();
        }
        return false;

        default:
            return false;
        }
        break;

    case DIR_INCOMING:
        switch (type) {
        case CT_LINK2: {
            m_reflector = connect.getRepeater();
            wxLogMessage(wxT("D-Plus dongle link to %s has started"), m_reflector.c_str());
            CConnectData reply(CT_ACK, m_address, m_port);
            m_handler->writeConnect(reply);
            m_linkState   = DPLUS_LINKED;
            m_stateChange = true;
        }
        return false;

        case CT_UNLINK:
            if (m_linkState == DPLUS_LINKED) {
                wxLogMessage(wxT("D-Plus dongle link to %s has ended (unlinked)"), m_reflector.c_str());
                m_stateChange = true;
                m_handler->writeConnect(connect);
            }
            return true;

        default:
            return false;
        }
        break;
    }

    return false;
}
void CDExtraHandler::process(CConnectData& connect)
{
	CD_TYPE type = connect.getType();

	if (type == CT_ACK || type == CT_NAK || type == CT_UNLINK) {
		for (unsigned int i = 0U; i < m_maxReflectors; i++) {
			if (m_reflectors[i] != NULL) {
				bool res = m_reflectors[i]->processInt(connect, type);
				if (res) {
					delete m_reflectors[i];
					m_reflectors[i] = NULL;
				}
			}
		}

		return;
	}

	// else if type == CT_LINK1 or type == CT_LINK2
	in_addr   address = connect.getAddress();
	unsigned int port = connect.getPort();

	wxString repeaterCallsign = connect.getRepeater();

	wxChar band = connect.getReflector().GetChar(LONG_CALLSIGN_LENGTH - 1U);

	wxString reflectorCallsign = m_callsign;
	reflectorCallsign.SetChar(LONG_CALLSIGN_LENGTH - 1U, band);

	// Check that it isn't a duplicate
	for (unsigned int i = 0U; i < m_maxReflectors; i++) {
		if (m_reflectors[i] != NULL) {
			if (m_reflectors[i]->m_direction      == DIR_INCOMING &&
			    m_reflectors[i]->m_address.s_addr == address.s_addr &&
			    m_reflectors[i]->m_port           == port &&
			    m_reflectors[i]->m_repeater.IsSameAs(reflectorCallsign) &&
			    m_reflectors[i]->m_reflector.IsSameAs(repeaterCallsign))
				return;
		}
	}

	// Check the validity of our repeater callsign
	IReflectorCallback* handler = CRepeaterHandler::findDVRepeater(reflectorCallsign);
	if (handler == NULL) {
		wxLogMessage(wxT("DExtra connect to unknown reflector %s from %s"), reflectorCallsign.c_str(), repeaterCallsign.c_str());
		CConnectData reply(repeaterCallsign, reflectorCallsign, CT_NAK, connect.getAddress(), connect.getPort());
		m_handler->writeConnect(reply);
		return;
	}

	// A new connect packet indicates the need for a new entry
	wxLogMessage(wxT("New incoming DExtra link to %s from %s"), reflectorCallsign.c_str(), repeaterCallsign.c_str());

	CDExtraHandler* dextra = new CDExtraHandler(handler, repeaterCallsign, reflectorCallsign, address, port, DIR_INCOMING);

	bool found = false;
	for (unsigned int i = 0U; i < m_maxReflectors; i++) {
		if (m_reflectors[i] == NULL) {
			m_reflectors[i] = dextra;
			found = true;
			break;
		}
	}

	if (found) {
		CConnectData reply(repeaterCallsign, reflectorCallsign, CT_ACK, address, port);
		m_handler->writeConnect(reply);

		wxString callsign = repeaterCallsign;
		callsign.SetChar(LONG_CALLSIGN_LENGTH - 1U, wxT(' '));
		CPollData poll(callsign, wxEmptyString, address, port);
		m_handler->writePoll(poll);
	} else {
		CConnectData reply(repeaterCallsign, reflectorCallsign, CT_NAK, address, port);
		m_handler->writeConnect(reply);

		wxLogError(wxT("No space to add new DExtra repeater, ignoring"));
		delete dextra;
	}
}
void CDPlusHandler::process(CConnectData& connect)
{
    CD_TYPE    type = connect.getType();
    in_addr address = connect.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) {
                bool res = m_reflectors[i]->processInt(connect, type);
                if (res) {
                    delete m_reflectors[i];
                    m_reflectors[i] = NULL;
                }
            }
        }
    }

    unsigned int port = connect.getPort();

    // Check that it isn't a duplicate
    for (unsigned int i = 0U; i < m_maxReflectors; i++) {
        if (m_reflectors[i] != NULL) {
            if (m_reflectors[i]->m_address.s_addr == address.s_addr)
                return;
        }
    }

    if (type == CT_UNLINK)
        return;

    if (type != CT_LINK1) {
        wxLogMessage(wxT("Incoming D-Plus message from unknown source"));
        return;
    }

    // Check to see if we are allowed to accept it
    unsigned int count = 0U;
    for (unsigned int i = 0U; i < m_maxReflectors; i++) {
        if (m_reflectors[i] != NULL &&
                m_reflectors[i]->m_direction == DIR_INCOMING)
            count++;
    }

    if (count >= m_maxDongles)
        return;

    CDPlusHandler* dplus = new CDPlusHandler(m_incoming, address, port);

    bool found = false;

    for (unsigned int i = 0U; i < m_maxReflectors; i++) {
        if (m_reflectors[i] == NULL) {
            m_reflectors[i] = dplus;
            found = true;
            break;
        }
    }

    if (found) {
        CConnectData connect(CT_LINK1, address, port);
        m_incoming->writeConnect(connect);
    } else {
        wxLogError(wxT("No space to add new D-Plus dongle, ignoring"));
        delete dplus;
    }
}