Exemplo n.º 1
0
/**
 Send the transmit buffer out over all designated interfaces, called as a
 timer callback and also immediately on an external state change.

 @param interfaces
 a bitmap defining which interfaces to send over
 */
static void txToAllOlsrInterfaces(TimedTxInterface interfaces) {
	/** txBuffer is used to concatenate the position update and cluster leader messages in */
	unsigned char txBuffer[TX_BUFFER_SIZE_FOR_OLSR];
	unsigned int txBufferBytesUsed = 0;
	#define txBufferBytesFree	(sizeof(txBuffer) - txBufferBytesUsed)

	/*
	 * The first message in txBuffer is an OLSR position update.
	 *
	 * The position update is always present.
	 *
	 * The second message is the cluster leader message, but only when uplink
	 * was requested and correctly configured.
	 */

	UplinkMessage * pu_uplink = (UplinkMessage *) &txBuffer[0];
	union olsr_message * pu = &pu_uplink->msg.olsrMessage;
	unsigned int pu_size = 0;
	union olsr_ip_addr gateway;
	MovementState externalState;
	nmeaINFO nmeaInfo;

	externalState = getExternalState();

	/* only fixup timestamp when the position is valid _and_ when the position was not updated */
	if (positionValid(&transmitGpsInformation.txPosition) && !transmitGpsInformation.positionUpdated) {
		nmea_time_now(&transmitGpsInformation.txPosition.nmeaInfo.utc, &transmitGpsInformation.txPosition.nmeaInfo.present);
	}

	nmeaInfo = transmitGpsInformation.txPosition.nmeaInfo;
	transmitGpsInformation.positionUpdated = false;
	gateway = transmitGpsInformation.txGateway;

	/* convert nmeaINFO to wireformat olsr message */
	txBufferBytesUsed += sizeof(UplinkHeader); /* keep before txBufferSpaceFree usage */
	pu_size = gpsToOlsr(&nmeaInfo, pu, txBufferBytesFree,
			((externalState == MOVEMENT_STATE_STATIONARY) ? getUpdateIntervalStationary() : getUpdateIntervalMoving()));
	txBufferBytesUsed += pu_size;

	/*
	 * push out to all OLSR interfaces
	 */
	if (((interfaces & TX_INTERFACE_OLSR) != 0) && getOlsrTtl() && (pu_size > 0)) {
		int r;
		struct interface *ifn;
		for (ifn = ifnet; ifn; ifn = ifn->int_next) {
			/* force the pending buffer out if there's not enough space for our message */
			if ((int)pu_size > net_outbuffer_bytes_left(ifn)) {
			  net_output(ifn);
			}
			r = net_outbuffer_push(ifn, pu, pu_size);
			if (r != (int) pu_size) {
				pudError(
						false,
						"Could not send to OLSR interface %s: %s (size=%u, r=%d)",
						ifn->int_name,
						((r == -1) ? "no buffer was found" :
							(r == 0) ? "there was not enough room in the buffer" : "unknown reason"), pu_size, r);
			}
		}

		/* loopback to tx interface when so configured */
		if (getUseLoopback()) {
			(void) packetReceivedFromOlsr(pu, NULL, NULL);
		}
	}

	/* push out over uplink when an uplink is configured */
	if (((interfaces & TX_INTERFACE_UPLINK) != 0) && isUplinkAddrSet()) {
		int fd = getDownlinkSocketFd();
		if (fd != -1) {
			union olsr_sockaddr * uplink_addr = getUplinkAddr();
			void * addr;
			socklen_t addrSize;

			UplinkMessage * cl_uplink = (UplinkMessage *) &txBuffer[txBufferBytesUsed];
			UplinkClusterLeader * cl = &cl_uplink->msg.clusterLeader;
			union olsr_ip_addr * cl_originator = getClusterLeaderOriginator(olsr_cnf->ip_version, cl);
			union olsr_ip_addr * cl_clusterLeader = getClusterLeaderClusterLeader(olsr_cnf->ip_version, cl);

			unsigned int cl_size =
					sizeof(UplinkClusterLeader) - sizeof(cl->leader)
							+ ((olsr_cnf->ip_version == AF_INET) ? sizeof(cl->leader.v4) :
									sizeof(cl->leader.v6));

			unsigned long long uplinkUpdateInterval =
					(externalState == MOVEMENT_STATE_STATIONARY) ? getUplinkUpdateIntervalStationary() : getUplinkUpdateIntervalMoving();

			if (uplink_addr->in.sa_family == AF_INET) {
				addr = &uplink_addr->in4;
				addrSize = sizeof(struct sockaddr_in);
			} else {
				addr = &uplink_addr->in6;
				addrSize = sizeof(struct sockaddr_in6);
			}

			/*
			 * position update message (pu)
			 */

			/* set header fields in position update uplink message and adjust
			 * the validity time to the uplink validity time */
			if (pu_size > 0) {
				PudOlsrPositionUpdate * pu_gpsMessage = getOlsrMessagePayload(olsr_cnf->ip_version, pu);

				setUplinkMessageType(&pu_uplink->header, POSITION);
				setUplinkMessageLength(&pu_uplink->header, pu_size);
				setUplinkMessageIPv6(&pu_uplink->header, (olsr_cnf->ip_version != AF_INET));
				setUplinkMessagePadding(&pu_uplink->header, 0);

				/* fixup validity time */
				setValidityTime(&pu_gpsMessage->validityTime, uplinkUpdateInterval);
			}

			/*
			 * cluster leader message (cl)
			 */

			/* set cl_uplink header fields */
			setUplinkMessageType(&cl_uplink->header, CLUSTERLEADER);
			setUplinkMessageLength(&cl_uplink->header, cl_size);
			setUplinkMessageIPv6(&cl_uplink->header, (olsr_cnf->ip_version != AF_INET));
			setUplinkMessagePadding(&cl_uplink->header, 0);

			/* setup cl */
			setClusterLeaderVersion(cl, PUD_WIRE_FORMAT_VERSION);
			setValidityTime(&cl->validityTime, uplinkUpdateInterval);

			/* really need 2 memcpy's here because of olsr_cnf->ipsize */
			memcpy(cl_originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
			memcpy(cl_clusterLeader, &gateway, olsr_cnf->ipsize);

			txBufferBytesUsed += sizeof(UplinkHeader);
			txBufferBytesUsed += cl_size;

			errno = 0;
			if (sendto(fd, &txBuffer, txBufferBytesUsed, 0, addr, addrSize) < 0) {
				pudError(true, "Could not send to uplink (size=%u)", txBufferBytesUsed);
			}
		}
	}
}
Exemplo n.º 2
0
void CFillTool::doFill() {
	// This is not the nicest code, but.. it works?

	auto map = widget()->map();
	int toReplace = map->get(m_whatType, m_hovered);

	if (toReplace == m_whatValue)
		return;

	QBitArray checked;
	checked.resize(map->width() * map->height());

	QQueue<CMapPoint> queue;
	queue.enqueue(m_hovered);

	while (!queue.isEmpty()) {
		CMapPoint point = queue.dequeue();

		int bitID = ((point.x / 2) * map->width()) + point.y;
		checked.setBit(bitID);

		CEditCommand::Change change;
		change.before = toReplace;
		change.after = m_whatValue;
		change.type = m_whatType;
		change.pos = point;
		m_command->changes.append(change);

		// Check every side to see what we've got to add to the list
		CMapPoint nw = point;
		nw.moveNW();
		int nwBit = ((nw.x / 2) * map->width()) + nw.y;
		if (map->positionValid(nw) && !checked.testBit(nwBit) && map->get(m_whatType, nw) == toReplace) {
			checked.setBit(nwBit);
			queue.enqueue(nw);
		}

		CMapPoint ne = point;
		ne.moveNE();
		int neBit = ((ne.x / 2) * map->width()) + ne.y;
		if (map->positionValid(ne) && !checked.testBit(neBit) && map->get(m_whatType, ne) == toReplace) {
			checked.setBit(neBit);
			queue.enqueue(ne);
		}

		CMapPoint sw = point;
		sw.moveSW();
		int swBit = ((sw.x / 2) * map->width()) + sw.y;
		if (map->positionValid(sw) && !checked.testBit(swBit) && map->get(m_whatType, sw) == toReplace) {
			checked.setBit(swBit);
			queue.enqueue(sw);
		}

		CMapPoint se = point;
		se.moveSE();
		int seBit = ((se.x / 2) * map->width()) + se.y;
		if (map->positionValid(se) && !checked.testBit(seBit) && map->get(m_whatType, se) == toReplace) {
			checked.setBit(seBit);
			queue.enqueue(se);
		}
	}

/*	while (!queue.isEmpty()) {
		CMapPoint point = queue.dequeue();

		// First off, check the NW side of this point
		CMapPoint check = point;

		while (true) {
			check.moveNW();
			if (!map->positionValid(check))
				break;
			if (map->get(m_whatType, check) != toReplace)
				break;

			int bitID = ((check.x / 2) * map->width()) + check.y;
			if (checked.testBit(bitID))
				break;
			checked.setBit(bitID);

			CEditCommand::Change change;
			change.before = toReplace;
			change.after = m_whatValue;
			change.type = m_whatType;
			change.pos = check;
			m_command->changes.append(change);

			// Check if we need to add anything SW/NE of this one
			CMapPoint checkSW = check;
			checkSW.moveSW();
			if (map->positionValid(checkSW) && map->get(m_whatType, checkSW) == toReplace)
				queue.enqueue(checkSW);

			CMapPoint checkNE = check;
			checkNE.moveNE();
			if (map->positionValid(checkNE) && map->get(m_whatType, checkNE) == toReplace)
				queue.enqueue(checkNE);
		}

		// Now check the SE side
		check = point;

		while (true) {
			check.moveSE();
			if (!map->positionValid(check))
				break;
			if (map->get(m_whatType, check) != toReplace)
				break;

			int bitID = ((check.x / 2) * map->width()) + check.y;
			if (checked.testBit(bitID))
				break;
			checked.setBit(bitID);

			CEditCommand::Change change;
			change.before = toReplace;
			change.after = m_whatValue;
			change.type = m_whatType;
			change.pos = check;
			m_command->changes.append(change);

			// Check if we need to add anything SW/NE of this one
			CMapPoint checkSW = check;
			checkSW.moveSW();
			if (map->positionValid(checkSW) && map->get(m_whatType, checkSW) == toReplace)
				queue.enqueue(checkSW);

			CMapPoint checkNE = check;
			checkNE.moveNE();
			if (map->positionValid(checkNE) && map->get(m_whatType, checkNE) == toReplace)
				queue.enqueue(checkNE);
		}
	}*/
}