public void reload_attach_inbound(ReloadMessage recmsg)
{
try
{
AttachReqAns req_answ = (AttachReqAns)recmsg.reload_message_body;
NodeId OriginatorID = recmsg.OriginatorID;
if (req_answ != null && req_answ.ice_candidates != null)
{
//if (ReloadGlobals.UseNoIce || m_ReloadConfig.IsBootstrap)
//{
//Node attacher = new Node(recmsg.OriginatorID, req_answ.ice_candidates); // markus, moved down
//bool isFinger = m_topology.routing_table.isFinger(attacher.Id);
//m_topology.routing_table.AddNode(attacher);
//m_topology.routing_table.SetNodeState(recmsg.OriginatorID, NodeState.attached);
//}
// incoming ATTACH REQUEST, so localnode is controlled agent
if (recmsg.IsRequest())
{
m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_RELOAD,
String.Format("{0} ==> {1} TransId={2:x16}",
RELOAD_MessageCode.Attach_Answer.ToString().PadRight(16, ' '),
OriginatorID, recmsg.TransactionID));
ReloadMessage sendmsg = create_attach_answ(
new Destination(OriginatorID), recmsg.TransactionID);
// log output
m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_INFO, String.Format("Attach Request: Transaction ID: {0:x}", recmsg.TransactionID));
foreach (IceCandidate cand in ((AttachReqAns)sendmsg.reload_message_body).ice_candidates)
m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_INFO, String.Format("Attach Request: Gathered local candidate for Answer: {0}:{1} (TransId: {2:x})", cand.addr_port.ipaddr.ToString(), cand.addr_port.port, sendmsg.TransactionID));
foreach (IceCandidate cand in req_answ.ice_candidates)
m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_INFO, String.Format("Attach Request: Received remote candidate: {0}:{1} (TransId: {2:x})", cand.addr_port.ipaddr.ToString(), cand.addr_port.port, recmsg.TransactionID));
recmsg.PutViaListToDestination(sendmsg);
//sendmsg.addOverlayForwardingOptions(recmsg); //Proprietary //--Joscha
if (m_machine is GWMachine)
{ //workaround in case date is stored at the gateway node responsible to route the message back into the interconnectionoverlay
if (sendmsg.forwarding_header.destination_list[0].destination_data.node_id == ((GWMachine)m_machine).GateWay.interDomainPeer.Topology.LocalNode.Id)
{
sendmsg.reload_message_body.RELOAD_MsgCode = RELOAD_MessageCode.Fetch_Answer;
((GWMachine)m_machine).GateWay.interDomainPeer.Transport.receive_message(sendmsg);
}
else
send(sendmsg, m_topology.routing_table.GetNode(recmsg.LastHopNodeId));
}
else
{
send(sendmsg, m_topology.routing_table.GetNode(recmsg.LastHopNodeId));
}
// markus
if (!ReloadGlobals.UseNoIce) // using ICE
{
// we only need ICE processing if localnode is a peer (in case of bootstrap we need no checks)
if (!m_ReloadConfig.IsBootstrap)
{
#region ICE TODO
// localnode is Peer => ICE processing (this is controlled node)
AttachReqAns attachAnswer = (AttachReqAns)sendmsg.reload_message_body;
// deep copy of local and remote ice candidates
List<IceCandidate> localIceCandidatesCopy = new List<IceCandidate>();
List<IceCandidate> remoteIceCandidatesCopy = new List<IceCandidate>();
// local candidates
foreach (IceCandidate cand in attachAnswer.ice_candidates)
{
IceCandidate deepCopy = (IceCandidate)cand.Clone();
localIceCandidatesCopy.Add(deepCopy);
}
// remote candidates
foreach (IceCandidate cand in req_answ.ice_candidates)
{
IceCandidate deepCopy = (IceCandidate)cand.Clone();
remoteIceCandidatesCopy.Add(deepCopy);
}
// now form check list
//CheckList checkList = ICE.FormCheckList(attachAnswer.ice_candidates, req_answ.ice_candidates, false);
CheckList checkList = ICE.FormCheckList(localIceCandidatesCopy, remoteIceCandidatesCopy, false);
ICE.PrintCandidatePairList(checkList.candidatePairs);
Console.WriteLine("ThreadId: {0}, send_params einfügen: checkList count {1}", Thread.CurrentThread.ManagedThreadId, checkList.candidatePairs.Count);
// Add to connection queue
for (int i = 0; i < checkList.candidatePairs.Count; i++)
{
ReloadSendParameters send_params = new ReloadSendParameters()
{
connectionTableEntry = null,
destinationAddress = checkList.candidatePairs[i].remoteCandidate.addr_port.ipaddr,
port = checkList.candidatePairs[i].remoteCandidate.addr_port.port,
buffer = null,
frame = false,
done = new Port<bool>(),
// markus
connectionSocket = null,
};
// if key already exists => skip
if (!GetForwardingAndLinkManagementLayer().GetConnectionQueue().ContainsKey(checkList.candidatePairs[i].remoteCandidate))
GetForwardingAndLinkManagementLayer().GetConnectionQueue().Add(checkList.candidatePairs[i].remoteCandidate, send_params);
}
ICE.ScheduleChecks(checkList, m_ReloadConfig.Logger);
// Wait for signals of all succeded candidate pairs. Only one of the succeded candidate pairs is nominated
#region signaling
// wait for nomination signal
List<Thread> waitingThreads = new List<Thread>();
foreach (CandidatePair candPair in checkList.candidatePairs)
{
if (candPair.state == CandidatePairState.Succeeded)
{
switch (candPair.localCandidate.tcpType)
{
case TcpType.Active:
{
if (candPair.localCandidate.activeConnectingSocket != null)
{
Thread waitThread = new Thread(() =>
{
candPair.nominated = ICE.WaitForSignal(candPair.localCandidate.activeConnectingSocket);
});
waitingThreads.Add(waitThread);
waitThread.Start();
}
}
break;
case TcpType.Passive:
{
if (candPair.localCandidate.passiveAcceptedSocket != null)
{
Thread waitThread = new Thread(() =>
{
candPair.nominated = ICE.WaitForSignal(candPair.localCandidate.passiveAcceptedSocket);
});
waitingThreads.Add(waitThread);
waitThread.Start();
}
}
break;
case TcpType.SO:
{
if (candPair.localCandidate.soAcceptedSocket != null)
{
Thread waitThread = new Thread(() =>
{
candPair.nominated = ICE.WaitForSignal(candPair.localCandidate.soAcceptedSocket);
});
waitingThreads.Add(waitThread);
waitThread.Start();
}
else if (candPair.localCandidate.soConnectingSocket != null)
{
Thread waitThread = new Thread(() =>
{
candPair.nominated = ICE.WaitForSignal(candPair.localCandidate.soConnectingSocket);
});
waitingThreads.Add(waitThread);
waitThread.Start();
}
}
break;
} // switch
} // if
} // foreach
// wait for all threads
foreach (Thread waitingThread in waitingThreads)
{
waitingThread.Join();
}
#endregion
// choose pair
CandidatePair choosenPair = null;
// any nominated pair?
if (checkList.candidatePairs.Any(item => item.nominated == true))
{
choosenPair = checkList.candidatePairs.First(item => item.nominated == true);
}
// Close all sockets of all candidate pairs not nominated
//for (int i = 0; i < checkList.candidatePairs.Count; i++)
// if ((!checkList.candidatePairs[i].nominated) || (checkList.candidatePairs[i].state != CandidatePairState.Succeeded))
// ICE.CloseAllCandidateSockets(checkList.candidatePairs[i].localCandidate);
// add node with chosen remote candidate
if (choosenPair != null)
{
// save connection
//GetForwardingAndLinkManagementLayer().SaveConnection(choosenPair);
// get connection
Socket socket = GetForwardingAndLinkManagementLayer().GetConnection(choosenPair);
// Get IPAdress and Port of the attacher from attachers certificate cn
System.Security.Cryptography.X509Certificates.X509Certificate2 tempcert = new System.Security.Cryptography.X509Certificates.X509Certificate2(recmsg.security_block.Certificates[0].Certificate);
IPEndPoint attacherEndpoint =
new IPEndPoint(IPAddress.Parse(tempcert.SubjectName.Name.ToString().Split(':')[1]),
Convert.ToInt32( tempcert.SubjectName.Name.ToString().Split(':')[2]));
// StartReloadTLSClient
GetForwardingAndLinkManagementLayer().StartReloadTLSClient(OriginatorID, socket, attacherEndpoint);
// for all candidates send_params.done = true
for (int i = 0; i < checkList.candidatePairs.Count; i++)
{
ReloadSendParameters send_params;
GetForwardingAndLinkManagementLayer().GetConnectionQueue().TryGetValue(checkList.candidatePairs[i].remoteCandidate, out send_params);
if (send_params != null)
{
send_params.done.Post(true);
// remove from connection queue
GetForwardingAndLinkManagementLayer().GetConnectionQueue().Remove(checkList.candidatePairs[i].remoteCandidate);
}
}
List<IceCandidate> choosenRemoteCandidates = new List<IceCandidate>();
choosenRemoteCandidates.Add(choosenPair.remoteCandidate);
Node attacher = new Node(recmsg.OriginatorID, choosenRemoteCandidates);
bool isFinger = m_topology.routing_table.isFinger(attacher.Id);
m_topology.routing_table.AddNode(attacher);
m_topology.routing_table.SetNodeState(recmsg.OriginatorID, NodeState.attached);
}
// free all port mappings created by UPnP
foreach (IceCandidate cand in attachAnswer.ice_candidates)
{
if (cand.cand_type == CandType.tcp_nat)
{
UPnP upnp = new UPnP();
bool discovered = upnp.Discover(cand.rel_addr_port.ipaddr);
if (discovered)
upnp.DeletePortMapping(cand.addr_port.port, ProtocolType.Tcp);
}
}
#endregion
}
else
{
// localnode is bootstrap => no ICE processing
Node attacher = new Node(recmsg.OriginatorID, req_answ.ice_candidates);
bool isFinger = m_topology.routing_table.isFinger(attacher.Id);
m_topology.routing_table.AddNode(attacher);
m_topology.routing_table.SetNodeState(recmsg.OriginatorID, NodeState.attached);
}
}
// using NO ICE
else
{
Node attacher = new Node(recmsg.OriginatorID, req_answ.ice_candidates);
bool isFinger = m_topology.routing_table.isFinger(attacher.Id);
m_topology.routing_table.AddNode(attacher);
m_topology.routing_table.SetNodeState(recmsg.OriginatorID, NodeState.attached);
}
// markus end
if (req_answ.SendUpdate)
Arbiter.Activate(m_DispatcherQueue, new IterativeTask<Node, Node>(
m_topology.routing_table.GetNode(OriginatorID),
m_topology.routing_table.GetNode(recmsg.LastHopNodeId),
SendUpdate));
}
// incoming ATTACH ANSWER, so localnode is controlling agent
// and localnode must be a peer, because bootstraps dont create attach requests and because of this cant receive an attach answer
else
{
// using NOICE
if (ReloadGlobals.UseNoIce) // markus: added if/else statement
{
m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR,
String.Format("{0} <== {1} (not handled!!)",
req_answ.RELOAD_MsgCode.ToString().PadRight(16, ' '), OriginatorID));
}
// using ICE
else
{
// get local candidates from request
List<IceCandidate> localCandidates = null;
bool gotLocalCandidate = m_attachRequestCandidates.TryGetValue(recmsg.TransactionID, out localCandidates);
// log output
m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_INFO, String.Format("Attach Answer: Transaction ID: {0:x}", recmsg.TransactionID));
foreach (IceCandidate cand in localCandidates)
m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_INFO, String.Format("Attach Answer: Got local candidate: {0}:{1} (TransId: {2:x})", cand.addr_port.ipaddr.ToString(), cand.addr_port.port, recmsg.TransactionID));
foreach (IceCandidate cand in req_answ.ice_candidates)
m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_INFO, String.Format("Attach Answer: Received remote candidate: {0}:{1} (TransId: {2:x})", cand.addr_port.ipaddr.ToString(), cand.addr_port.port, recmsg.TransactionID));
if (req_answ.ice_candidates != null)
{
// we need ice, except the answering peer is a bootstrap
bool needIce = true;
//// bootstrap responses with only one candidate
//if (req_answ.ice_candidates.Count == 1)
//{
// is it really a bootstrap?
if (req_answ.ice_candidates[0].cand_type == CandType.tcp_bootstrap)
{
// attached to a bootstrap, so we have to do nothing here, no ice processing needed
needIce = false;
}
//}
if (needIce)
{
#region ICE TODO
// ICE processing (this is controlling node)
if (gotLocalCandidate)
{
// deep copy of remote ice candidates
List<IceCandidate> remoteIceCandidatesCopy = new List<IceCandidate>();
// remote candidates
foreach (IceCandidate cand in req_answ.ice_candidates)
{
IceCandidate deepCopy = (IceCandidate)cand.Clone();
remoteIceCandidatesCopy.Add(deepCopy);
}
//CheckList checkList = ICE.FormCheckList(localCandidates, req_answ.ice_candidates, true);
CheckList checkList = ICE.FormCheckList(localCandidates, remoteIceCandidatesCopy, true);
ICE.PrintCandidatePairList(checkList.candidatePairs);
ICE.ScheduleChecks(checkList, m_ReloadConfig.Logger);
m_attachRequestCandidates.Remove(recmsg.TransactionID);
#region signaling
// any succeeded pair?
if (checkList.candidatePairs.Any(item => item.state == CandidatePairState.Succeeded))
{
// get all succeeded pairs
List<CandidatePair> succeededPairs = checkList.candidatePairs.Where(item => item.state == CandidatePairState.Succeeded).ToList();
// send nomination signal to peer
bool sentSuccessfull = false;
bool nominated;
int counter = 0;
foreach (CandidatePair pair in succeededPairs)
{
// simply nominate the first succeeded pair
if (counter == 0)
nominated = true;
else
nominated = false;
switch (pair.localCandidate.tcpType)
{
case TcpType.Active:
{
if (pair.localCandidate.activeConnectingSocket != null)
{
sentSuccessfull = ICE.SendSignal(pair.localCandidate.activeConnectingSocket, nominated);
pair.nominated = nominated;
}
}
break;
case TcpType.Passive:
{
if (pair.localCandidate.passiveAcceptedSocket != null)
{
sentSuccessfull = ICE.SendSignal(pair.localCandidate.passiveAcceptedSocket, nominated);
pair.nominated = nominated;
}
}
break;
case TcpType.SO:
{
if (pair.localCandidate.soAcceptedSocket != null)
{
sentSuccessfull = ICE.SendSignal(pair.localCandidate.soAcceptedSocket, nominated);
pair.nominated = nominated;
}
else if (pair.localCandidate.soConnectingSocket != null)
{
sentSuccessfull = ICE.SendSignal(pair.localCandidate.soConnectingSocket, nominated);
pair.nominated = nominated;
}
}
break;
} // switch
counter++;
} // foreach
if (sentSuccessfull)
{
}
#endregion // signaling
// Start Server here, if a nominated pair exists
if (checkList.candidatePairs.Any(item => item.nominated))
{
CandidatePair choosenPair = checkList.candidatePairs.First(item => item.nominated);
// save connection here too?
//GetForwardingAndLinkManagementLayer().SaveConnection(choosenPair);
// get connection
Socket socket = GetForwardingAndLinkManagementLayer().GetConnection(choosenPair);
// StartReloadTLSServer
GetForwardingAndLinkManagementLayer().StartReloadTLSServer(socket);
} // if (any nominated)
} // if (any succeeded pair)
// Close all sockets of all candidate pairs not nominated
//for (int i = 0; i < checkList.candidatePairs.Count; i++)
// if ((!checkList.candidatePairs[i].nominated) || (checkList.candidatePairs[i].state != CandidatePairState.Succeeded))
// ICE.CloseAllCandidateSockets(checkList.candidatePairs[i].localCandidate);
}
#endregion // ICE
}
// existing nat candidates to free?
if (localCandidates != null)
{
// free all port mappings created by UPnP
foreach (IceCandidate cand in localCandidates)
{
if (cand.cand_type == CandType.tcp_nat)
{
UPnP upnp = new UPnP();
bool discovered = upnp.Discover(cand.rel_addr_port.ipaddr);
if (discovered)
upnp.DeletePortMapping(cand.addr_port.port, ProtocolType.Tcp);
}
}
}
}
}
}
}
}
catch (Exception e)
{
throw;
}
}