public void StartReloadTLSClient(NodeId nodeid, Socket socket, IPEndPoint attacherEndpoint) { // simply call InitReloadTLSClient ReloadSendParameters send_params = new ReloadSendParameters(); send_params.destinationAddress = attacherEndpoint.Address; link.InitReloadTLSClient(send_params, socket, attacherEndpoint); if (send_params.connectionTableEntry != null) { ReloadConnectionTableEntry connectionTableEntry = send_params.connectionTableEntry; //TODO: not nice but does the trick if (send_params.connectionTableEntry.NodeID != null) //TODO: correct? nodeid = send_params.connectionTableEntry.NodeID; } }
public IEnumerator<ITask> Send(Node node, ReloadMessage reloadMessage) // node is remote peer { ReloadConnectionTableEntry connectionTableEntry = null; List<Byte[]> ByteArrayList = new List<byte[]>(); ByteArrayList.Add(reloadMessage.ToBytes()); //if (ReloadGlobals.FRAGMENTATION == true) { if (reloadMessage.forwarding_header.length > ReloadGlobals.MAX_PACKET_BUFFER_SIZE * ReloadGlobals.MAX_PACKETS_PER_RECEIVE_LOOP) { if (ByteArrayList[0].Length > ReloadGlobals.FRAGMENT_SIZE) { //TODO: fragment size should not be fix ByteArrayList.Clear(); ByteArrayList = reloadMessage.ToBytesFragmented(ReloadGlobals.FRAGMENT_SIZE); } } foreach (byte[] ByteArray in ByteArrayList) { /* Try to find a matching connection using node id or target address*/ if (node.Id != null) { connectionTableEntry = connectionTable.lookupEntry(node.Id); if (connectionTableEntry != null) m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_SOCKET, String.Format("FLM: Found open connection for target node id {0}", node.Id)); } if (connectionTableEntry == null) { // connectionTableEntry == null => no connection to remote peer List<IceCandidate> icecandidates = node.IceCandidates; // remote peer candidates if (icecandidates != null) { foreach (IceCandidate candidate in icecandidates) { switch (candidate.addr_port.type) { case AddressType.IPv6_Address: case AddressType.IPv4_Address: { ReloadSendParameters send_params; // check if there is already a attempt to open a connection to this node //if (connectionQueue.ContainsKey(candidate.addr_port)) if (connectionQueue.ContainsKey(candidate)) { // here we have a connection attempt m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_WARNING, String.Format("Connection Pending!!!!!!!!!!!!!!!!!!!!!!!!!!!")); //send_params = connectionQueue[candidate.addr_port]; send_params = connectionQueue[candidate]; yield return Arbiter.Receive(false, send_params.done, x => { }); send_params.done.Post(true); //maybe there are still some other pending connections? if (send_params.connectionTableEntry != null) //do we have a valid connection? { // here we have a valid connection connectionTableEntry = send_params.connectionTableEntry; if (send_params.connectionTableEntry.NodeID != null) //TODO: correct? node.Id = send_params.connectionTableEntry.NodeID; m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_WARNING, String.Format("DONE!!!!!!!!!!!!!!!!!!!!!!!!!!!")); //connectionQueue.Remove(candidate.addr_port); connectionQueue.Remove(candidate); if (node.Id != null) { connectionTableEntry = connectionTable.lookupEntry(node.Id); if (connectionTableEntry != null) m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_SOCKET, String.Format("FLM: Found open connection for target node id {0}", node.Id)); send_params = new ReloadSendParameters() { connectionTableEntry = connectionTableEntry, destinationAddress = null, port = 0, buffer = ByteArray, frame = true, done = new Port<bool>(), // markus connectionSocket = null, }; yield return Arbiter.ExecuteToCompletion(m_DispatcherQueue, new IterativeTask<Node, ReloadSendParameters>(node, send_params, link.Send)); // SEND break; } } // here we have no valid connection, but a connection attempt (maybe break?) //break; // markus } // no connection attempt (maybe else here?) // here is no existing connection and no attempt => try to connect // NO ICE or ICE but bootstrap if (ReloadGlobals.UseNoIce || candidate.cand_type == CandType.tcp_bootstrap) { connectionTableEntry = connectionTable.lookupEntry(new IPEndPoint(candidate.addr_port.ipaddr, candidate.addr_port.port)); if (connectionTableEntry != null) m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_TRANSPORT, String.Format("FLM: Found open connection for target IP {0}:{1}", candidate.addr_port.ipaddr, candidate.addr_port.port)); else m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_TRANSPORT, String.Format("Opening connection to {0}:{1}", candidate.addr_port.ipaddr, candidate.addr_port.port)); send_params = new ReloadSendParameters() { connectionTableEntry = connectionTableEntry, destinationAddress = candidate.addr_port.ipaddr, port = candidate.addr_port.port, buffer = ByteArray, frame = true, done = new Port<bool>(), // markus connectionSocket = null, }; //send_params.done.Post(false); //connectionQueue[candidate.addr_port] = send_params; connectionQueue[candidate] = send_params; //m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_INFO, String.Format("Insert {0}:{1} into connectionQueue", new IPAddress(send_params.destinationAddress.Address).ToString(), send_params.port)); yield return Arbiter.ExecuteToCompletion(m_DispatcherQueue, new IterativeTask<Node, ReloadSendParameters>(node, send_params, link.Send)); // SEND //connectionQueue.Remove(candidate.addr_port); connectionQueue.Remove(candidate); if (send_params.connectionTableEntry != null) { connectionTableEntry = send_params.connectionTableEntry; //TODO: not nice but does the trick if (send_params.connectionTableEntry.NodeID != null) //TODO: correct? node.Id = send_params.connectionTableEntry.NodeID; } } // ICE peer //else //{ // connectionTableEntry = connectionTable.lookupEntry(new IPEndPoint(candidate.addr_port.ipaddr, candidate.addr_port.port)); // if (connectionTableEntry != null) // m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_TRANSPORT, String.Format("FLM: Found open connection for target IP {0}:{1}", candidate.addr_port.ipaddr, candidate.addr_port.port)); // else // m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_TRANSPORT, String.Format("Opening connection to {0}:{1}", candidate.addr_port.ipaddr, candidate.addr_port.port)); // // try to get connection // Socket connectionSocket = null; // m_connectionsToRemotePeer.TryGetValue(candidate.addr_port, out connectionSocket); // //if (connectionSocket == null) // // continue; //versuche mit nächsten candidate // send_params = new ReloadSendParameters() // { // connectionTableEntry = connectionTableEntry, // destinationAddress = candidate.addr_port.ipaddr, // port = candidate.addr_port.port, // buffer = ByteArray, // frame = true, // done = new Port<bool>(), // // markus // connectionSocket = connectionSocket, // }; // //send_params.done.Post(false); // connectionQueue[candidate.addr_port] = send_params; // yield return Arbiter.ExecuteToCompletion(m_DispatcherQueue, new IterativeTask<Node, ReloadSendParameters>(node, send_params, link.Send)); // SEND // connectionQueue.Remove(candidate.addr_port); // if (send_params.connectionTableEntry != null) // { // connectionTableEntry = send_params.connectionTableEntry; //TODO: not nice but does the trick // if (send_params.connectionTableEntry.NodeID != null) //TODO: correct? // node.Id = send_params.connectionTableEntry.NodeID; // } //} } break; } //just support one ice candidate only here break; } // foreach ice candidate } } else { // connectionTableEntry != null => existing connection to remote peer ReloadSendParameters send_params = new ReloadSendParameters() { connectionTableEntry = connectionTableEntry, destinationAddress = null, port = 0, buffer = ByteArray, frame = true, done = new Port<bool>(), }; yield return Arbiter.ExecuteToCompletion(m_DispatcherQueue, new IterativeTask<Node, ReloadSendParameters>(node, send_params, link.Send)); // SEND } } // foreach ByteArray yield break; } // Send
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; } }