public void HandleData(AHHeader header, ICopyable payload, ISender ret_path, object st) {
AHState state = _state; //Read the state, it can't change after the read
Connection next_con;
//Check to see if we can use a Leaf connection:
int dest_idx = state.Leafs.IndexOf(header.Destination);
if( dest_idx >= 0 ) {
next_con = state.Leafs[dest_idx];
} else {
var alg = state.GetRoutingAlgo(header);
Pair<Connection, bool> result = alg.NextConnection(ret_path as Edge, header);
if( result.Second ) {
//Send a response exactly back to the node that sent to us
var resp_send = new AHSender(_n, ret_path, header.Source,
AHSender.DefaultTTLFor(_n.NetworkSize),
AHHeader.Options.Exact, header.Hops);
MemBlock data = payload as MemBlock;
if(data == null) {
// Try to get the shared BufferAllocator, useful when we don't know
// how big the data is, which in general is just as expensive as
// doing a CopyTo...
BufferAllocator ba = Interlocked.Exchange<BufferAllocator>(ref _ba, null);
if( ba != null ) {
try {
int length = payload.CopyTo(ba.Buffer, ba.Offset);
data = MemBlock.Reference(ba.Buffer, ba.Offset, length);
ba.AdvanceBuffer(length);
} catch(System.Exception x) {
throw new SendException(false, "could not write the packet, is it too big?", x);
} finally {
Interlocked.Exchange<BufferAllocator>(ref _ba, ba);
}
} else {
data = MemBlock.Copy(payload);
}
}
_n.HandleData( data, resp_send, this);
}
next_con = result.First;
}
//Send it on:
if( next_con != null ) {
//Now we do the sending:
var new_packet = new CopyList(PType.Protocol.AH,
header.IncrementHops(),
payload);
try {
next_con.State.Edge.Send(new_packet);
}
catch(SendException) {
//Just drop the packet...
}
}
}