@Override
	public synchronized Nexthops lookup(Data scaledDestinationAddress, Address originAddress, Object originIdentifierObject, int offset) {
		
		if(connectedCircleRoutingTable != null) {
			return connectedCircleRoutingTable.lookup(scaledDestinationAddress, originAddress, originIdentifierObject, offset);
		}
		
		// check if the destination address refers to one of our local endpoints
		Nexthops nexthops = localEndpointRoutes.get(scaledDestinationAddress);
		if(nexthops != null) {
			// great, the packet belongs to us
			
			// before returning the list of nexthops (which are only local endpoints at this point), check
			// if there are any neighbors with the same scaled address and if yes, add them to the nexthops
			// list, as long as we did not already receive this packet from such a twin neighbor
			Nexthops twinNeighbors = remoteServiceRoutes.get(scaledDestinationAddress); // here, use get() instead of getClosest()
			if(twinNeighbors != null) {
				
				boolean append = true;
				
				for(ForwardDestination forwardDestination : twinNeighbors) {
					if(forwardDestination.getIdentifierObject() == originIdentifierObject) {
						// if we already received the packet from such a twin neighbor,
						// don't loop-route it back.
						// note: all the hops in the twinNexthops list share the same scaled address
						//       as us, and if one of their ForwardDestinations holds the originAddress
						//       Address instance, we received the packet from that hop, who also takes
						//       care of forwarding the packet to the other twins. just locally deliver the packet.
						append = false;
						break;
					}
				}
				
				if(append) {
					nexthops.append(twinNeighbors);
				}
				
			}
			
			return nexthops;
		}
		
		// looks like we don't have a local endpoint for this address, so check if we can forward
		// it to somebody who's closer to the destination
		
		nexthops = remoteServiceRoutes.getClosest(scaledDestinationAddress);
		
		if(nexthops == null) {
			// nothing found
			return null;
		}
		
		for(ForwardDestination forwardDestination : nexthops) {
			if(forwardDestination.getIdentifierObject() == originIdentifierObject) {
				// to prevent loop-routing, do not forward the packet at all if the
				// the hop we just received it from is included in the nexthops list
				return null;
			}
		}
		
		// now, only forward to one hop. if there are more than one hops with the same
		// scaled address (which is the case if nexthops contains more than one
		// ForwardDestination), the hop we forward the packet to will be connected to its
		// twins and share the packet with them.
		
		return nexthops.getLast();
		
	}