Exemple #1
0
////////////////////////////////////////////////////////////////////
// Called by RF22Router::recvfromAck whenever a message goes past
void RF22Mesh::peekAtMessage(RoutedMessage* message, uint8_t messageLen)
{
    MeshMessageHeader* m = (MeshMessageHeader*)message->data;
    if (   messageLen > 1 
	&& m->msgType == RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE)
    {
	// This is a unicast RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE messages 
	// being routed back to the originator here. Want to scrape some routing data out of the response
	// We can find the routes to all the nodes between here and the responding node
	MeshRouteDiscoveryMessage* d = (MeshRouteDiscoveryMessage*)message->data;
	addRouteTo(d->dest, headerFrom());
	uint8_t numRoutes = messageLen - sizeof(RoutedMessageHeader) - sizeof(MeshMessageHeader) - 2;
	uint8_t i;
	// Find us in the list of nodes that were traversed to get to the responding node
	for (i = 0; i < numRoutes; i++)
	    if (d->route[i] == _thisAddress)
		break;
	i++;
	while (i++ < numRoutes)
	    addRouteTo(d->route[i], headerFrom());
    }
    else if (   messageLen > 1 
	     && m->msgType == RF22_MESH_MESSAGE_TYPE_ROUTE_FAILURE)
    {
	MeshRouteFailureMessage* d = (MeshRouteFailureMessage*)message->data;
	deleteRouteTo(d->dest);
    }
}
Exemple #2
0
bool RHMesh::doArp(uint8_t address)
{
    // Need to discover a route
    // Broadcast a route discovery message with nothing in it
    MeshRouteDiscoveryMessage* p = (MeshRouteDiscoveryMessage*)&_tmpMessage;
    p->header.msgType = RH_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST;
    p->destlen = 1; 
    p->dest = address; // Who we are looking for
    uint8_t error = RHRouter::sendtoWait((uint8_t*)p, sizeof(RHMesh::MeshMessageHeader) + 2, RH_BROADCAST_ADDRESS);
    if (error !=  RH_ROUTER_ERROR_NONE)
	return false;
    
    // Wait for a reply, which will be unicast back to us
    // It will contain the complete route to the destination
    uint8_t messageLen = sizeof(_tmpMessage);
    // FIXME: timeout should be configurable
    unsigned long starttime = millis();
    while ((millis() - starttime) < 4000)
    {
	if (RHRouter::recvfromAck(_tmpMessage, &messageLen))
	{
	    if (   messageLen > 1
		&& p->header.msgType == RH_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE)
	    {
		// Got a reply, now add the next hop to the dest to the routing table
		// The first hop taken is the first octet
		addRouteTo(address, headerFrom());
		return true;
	    }
	}
	YIELD;
    }
    return false;
}
boolean RF22ReliableDatagram::sendtoWait(uint8_t* buf, uint8_t len, uint8_t address)
{
    // Assemble the message
    uint8_t thisSequenceNumber = ++_lastSequenceNumber;

    Timer t;

    uint8_t retries = 0;
    while (retries++ <= _retries)
    {
        setHeaderId(thisSequenceNumber);
        setHeaderFlags(0);
        sendto(buf, len, address);
        waitPacketSent(3000);

        // Never wait for ACKS to broadcasts:
        if (address == RF22_BROADCAST_ADDRESS)
            return true;

        if (retries > 1)
            _retransmissions++;
        t.start();
        unsigned long thisSendTime = t.read_ms(); // Timeout does not include original transmit time


        // Compute a new timeout, random between _timeout and _timeout*2
    // This is to prevent collisions on every retransmit
        // if 2 nodes try to transmit at the same time
        uint16_t timeout = _timeout + (_timeout * (rand() % 100) / 100);
        while (t.read_ms() < (thisSendTime + timeout)) 
        {
            if (available()) {
                clearRxBuf(); // Not using recv, so clear it ourselves
                uint8_t from = headerFrom();
                uint8_t to = headerTo();
                uint8_t id = headerId();
                uint8_t flags = headerFlags();
                // Now have a message: is it our ACK?
                if (   from == address
                        && to == _thisAddress
                        && (flags & RF22_FLAGS_ACK)
            && (id == thisSequenceNumber))
        {
                    // Its the ACK we are waiting for
                    return true;
        }
        else if (   !(flags & RF22_FLAGS_ACK)
             && (id == _seenIds[from]))
        {
                    // This is a request we have already received. ACK it again
                    acknowledge(id, from);
                }
                // Else discard it
            }
            // Not the one we are waiting for, maybe keep waiting until timeout exhausted
        }
        // Timeout exhausted, maybe retry
    }
    return false;
}
Exemple #4
0
boolean RF22Datagram::recvfrom(uint8_t* buf, uint8_t* len, uint8_t* from, uint8_t* to, uint8_t* id, uint8_t* flags)
{
    if (from)  *from =  headerFrom();
    if (to)    *to =    headerTo();
    if (id)    *id =    headerId();
    if (flags) *flags = headerFlags();
    return recv(buf, len);
}
bool RHDatagram::recvfrom(uint8_t* buf, uint8_t* len, uint8_t* from, uint8_t* to, uint8_t* id, uint8_t* flags)
{
    if (_driver.recv(buf, len))
    {
	if (from)  *from =  headerFrom();
	if (to)    *to =    headerTo();
	if (id)    *id =    headerId();
	if (flags) *flags = headerFlags();
	return true;
    }
    return false;
}
Exemple #6
0
////////////////////////////////////////////////////////////////////
// This is called when a message is to be delivered to the next hop
uint8_t RF22Mesh::route(RoutedMessage* message, uint8_t messageLen)
{
    uint8_t from = headerFrom(); // Might get clobbered during call to superclass route()
    uint8_t ret = RF22Router::route(message, messageLen);
    if (   ret == RF22_ROUTER_ERROR_NO_ROUTE
	|| ret == RF22_ROUTER_ERROR_UNABLE_TO_DELIVER)
    {
	// Cant deliver to the next hop. Delete the route
	deleteRouteTo(message->header.dest);
	if (message->header.source != _thisAddress)
	{
	    // This is being proxied, so tell the originator about it
	    MeshRouteFailureMessage* p = (MeshRouteFailureMessage*)&_tmpMessage;
	    p->header.msgType = RF22_MESH_MESSAGE_TYPE_ROUTE_FAILURE;
	    p->dest = message->header.dest; // Who you were trying to deliver to
	    // Make sure there is a route back towards whoever sent the original message
	    addRouteTo(message->header.source, from);
	    ret = RF22Router::sendtoWait((uint8_t*)p, sizeof(RF22Mesh::MeshMessageHeader) + 1, message->header.source);
	}
    }
    return ret;
}
Exemple #7
0
boolean RF22Mesh::recvfromAck(uint8_t* buf, uint8_t* len, uint8_t* source, uint8_t* dest, uint8_t* id, uint8_t* flags)
{     
    uint8_t tmpMessageLen = sizeof(_tmpMessage);
    uint8_t _source;
    uint8_t _dest;
    uint8_t _id;
    uint8_t _flags;
    uint8_t frags = 0;
    uint8_t offset = 0;
    uint8_t total_len = 0;
    uint8_t seq_no = 0;
    uint8_t x = 0, y = 0;
    uint8_t loop_once = 1;
    uint8_t have_message = 0;

    #ifndef CLIENT
    lcd.begin( 20, 4 );
    lcd.clear();
    #endif

    while( frags > 0 || loop_once == 1 ) {
        loop_once = 0;
        if (RF22Router::recvfromAck(_tmpMessage, &tmpMessageLen, &_source, &_dest, &_id, &_flags))
        {
            MeshMessageHeader* p = (MeshMessageHeader*)&_tmpMessage;

            if (   tmpMessageLen >= 1 
                && p->msgType == RF22_MESH_MESSAGE_TYPE_APPLICATION)
            {
                have_message = 1;

                MeshApplicationMessage* a = (MeshApplicationMessage*)p;
                // Handle application layer messages, presumably for our caller

                if (source) *source = _source;
                if (dest)   *dest   = _dest;
                if (id)     *id     = _id;
                if (flags)  *flags  = _flags;
                uint8_t msgLen = tmpMessageLen - sizeof(MeshMessageHeader);
                if (*len > msgLen)
                    *len = msgLen;

                frags = a->header.frag;
                #ifdef CLIENT
                Serial.print( F( "RF22Mesh::recvfromAck frags: " ) );
                Serial.println( frags );
                #endif



                seq_no = a->header.seqno;
                if( frags > 0 || (frags == 0 && a->header.seqno > 0 ) ) {
                    offset = a->header.seqno * RF22_MESH_MAX_MESSAGE_LEN;
                }

                #ifdef CLIENT
                for( int i = 0; i < *len; i++ ) {
                    Serial.print( a->data[i] );
                    Serial.print( F( ", " ) );
                }
                Serial.println( F( "" ) );
                #endif
                
                memcpy( buf + offset, a->data, *len );

                #ifndef CLIENT
                lcd.setCursor( x, y );
                lcd.print( *len );
                if( ( x + 8 ) > 20 ) {
                    y++;
                    x = 0;
                } else {
                    x += 4;
                }
                #endif

            }
            else if (   _dest == RF22_BROADCAST_ADDRESS 
                     && tmpMessageLen > 1 
                     && p->msgType == RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST)
            {
                MeshRouteDiscoveryMessage* d = (MeshRouteDiscoveryMessage*)p;
                // Handle Route discovery requests
                // Message is an array of node addresses the route request has already passed through
                // If it originally came from us, ignore it
                if (_source == _thisAddress)
                    return false;
                
                uint8_t numRoutes = tmpMessageLen - sizeof(MeshMessageHeader) - 2;
                uint8_t i;
                // Are we already mentioned?
                for (i = 0; i < numRoutes; i++)
                    if (d->route[i] == _thisAddress)
                        return false; // Already been through us. Discard
                
                // Hasnt been past us yet, record routes back to the earlier nodes
                addRouteTo(_source, headerFrom()); // The originator
                for (i = 0; i < numRoutes; i++)
                    addRouteTo(d->route[i], headerFrom());
                if (isPhysicalAddress(&d->dest, d->destlen))
                {
                    // This route discovery is for us. Unicast the whole route back to the originator
                    // as a RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE
                    // We are certain to have a route there, becuase we just got it
                    d->header.msgType = RF22_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE;
                    RF22Router::sendtoWait((uint8_t*)d, tmpMessageLen, _source);
                }
                else if (i < _max_hops)
                {
                    // Its for someone else, rebroadcast it, after adding ourselves to the list
                    d->route[numRoutes] = _thisAddress;
                    tmpMessageLen++;
                    // Have to impersonate the source
                    // REVISIT: if this fails what can we do?
                    RF22Router::sendtoWait(_tmpMessage, tmpMessageLen, RF22_BROADCAST_ADDRESS, _source);
                }
            }
        } else if( frags == 0 ) {
            return false;
        } else {
            #ifdef CLIENT
            Serial.print( F( "corner case: frags: " ) );
            Serial.print( frags );
            Serial.print( F( "loop_once: " ) );
            Serial.println( loop_once );
            #endif
        }
    }

    if( have_message == 1 ) {
        *len = *len + ( seq_no * RF22_MESH_MAX_MESSAGE_LEN );

        #ifdef CLIENT
        Serial.print( F( "if have_message: frags: " ) );
        Serial.print( frags );
        Serial.print( F( "loop_once: " ) );
        Serial.println( loop_once );
        #endif

        #ifndef CLIENT
        lcd.setCursor( x, y );
        lcd.print( "t" );
        lcd.print( *len );
        #endif

        return true;
    } else {
        return false;
    }
}
Exemple #8
0
bool RHMesh::recvfromAck(uint8_t* buf, uint8_t* len, uint8_t* source, uint8_t* dest, uint8_t* id, uint8_t* flags)
{     
    uint8_t tmpMessageLen = sizeof(_tmpMessage);
    uint8_t _source;
    uint8_t _dest;
    uint8_t _id;
    uint8_t _flags;
    if (RHRouter::recvfromAck(_tmpMessage, &tmpMessageLen, &_source, &_dest, &_id, &_flags))
    {
	MeshMessageHeader* p = (MeshMessageHeader*)&_tmpMessage;

	if (   tmpMessageLen >= 1 
	    && p->msgType == RH_MESH_MESSAGE_TYPE_APPLICATION)
	{
	    MeshApplicationMessage* a = (MeshApplicationMessage*)p;
	    // Handle application layer messages, presumably for our caller
	    if (source) *source = _source;
	    if (dest)   *dest   = _dest;
	    if (id)     *id     = _id;
	    if (flags)  *flags  = _flags;
	    uint8_t msgLen = tmpMessageLen - sizeof(MeshMessageHeader);
	    if (*len > msgLen)
		*len = msgLen;
	    memcpy(buf, a->data, *len);
	    
	    return true;
	}
	else if (   _dest == RH_BROADCAST_ADDRESS 
		 && tmpMessageLen > 1 
		 && p->msgType == RH_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_REQUEST)
	{
	    MeshRouteDiscoveryMessage* d = (MeshRouteDiscoveryMessage*)p;
	    // Handle Route discovery requests
	    // Message is an array of node addresses the route request has already passed through
	    // If it originally came from us, ignore it
	    if (_source == _thisAddress)
		return false;
	    
	    uint8_t numRoutes = tmpMessageLen - sizeof(MeshMessageHeader) - 2;
	    uint8_t i;
	    // Are we already mentioned?
	    for (i = 0; i < numRoutes; i++)
		if (d->route[i] == _thisAddress)
		    return false; // Already been through us. Discard
	    
	    // Hasnt been past us yet, record routes back to the earlier nodes
	    addRouteTo(_source, headerFrom()); // The originator
	    for (i = 0; i < numRoutes; i++)
		addRouteTo(d->route[i], headerFrom());
	    if (isPhysicalAddress(&d->dest, d->destlen))
	    {
		// This route discovery is for us. Unicast the whole route back to the originator
		// as a RH_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE
		// We are certain to have a route there, becuase we just got it
		d->header.msgType = RH_MESH_MESSAGE_TYPE_ROUTE_DISCOVERY_RESPONSE;
		RHRouter::sendtoWait((uint8_t*)d, tmpMessageLen, _source);
	    }
	    else if (i < _max_hops)
	    {
		// Its for someone else, rebroadcast it, after adding ourselves to the list
		d->route[numRoutes] = _thisAddress;
		tmpMessageLen++;
		// Have to impersonate the source
		// REVISIT: if this fails what can we do?
		RHRouter::sendtoWait(_tmpMessage, tmpMessageLen, RH_BROADCAST_ADDRESS, _source);
	    }
	}
    }
    return false;
}