/// <summary> /// This method start the . /// </summary> public void Start() { int size = 0; TrafficType traffTypes; lock (ThreadTypeData) { if (idxThreadTypeData < ThreadTypeData.Length) { traffTypes = ThreadTypeData[idxThreadTypeData]; Thread.CurrentThread.Name = "Reflector_MCtoUC_" + traffTypes.ToString(); idxThreadTypeData++; } else { throw new Exception(Strings.CreatedThreadsExceedThreadTypesDefined); } } #region Assigning appropriate sockets to "(mc/uc)(Ref/Srv)Sock" // The Ref(erence) socket variables are assigned to the socket protocol that this thread is not listening on // but may use for inter-protocol communication. For example if mcSrvSock is an IPv4 socket, mcRefSock would be // an IPv6 socket and vice versa. IPEndPoint ipepTmpRef = null; IPEndPoint ipepTmpSrv = null; Socket ucRefSock = null; Socket mcSrvSock = null; Socket ucSrvSock = null; int ucPort = 0; int mcPort = 0; switch (traffTypes) { case TrafficType.IPv4RTCP: ucPort = ReflectorMgr.ReflectorUnicastRTPListenPort + 1; mcPort = ReflectorMgr.ReflectorMulticastRTPListenPort + 1; ipepTmpRef = new IPEndPoint(IPAddress.IPv6Any, 0); ipepTmpSrv = new IPEndPoint(IPAddress.Any, 0); ucRefSock = ReflectorMgr.Sockets.SockUCv6RTCP; mcSrvSock = ReflectorMgr.Sockets.SockMCv4RTCP; ucSrvSock = ReflectorMgr.Sockets.SockUCv4RTCP; break; case TrafficType.IPv6RTCP: ucPort = ReflectorMgr.ReflectorUnicastRTPListenPort + 1; mcPort = ReflectorMgr.ReflectorMulticastRTPListenPort + 1; ipepTmpSrv = new IPEndPoint(IPAddress.IPv6Any, 0); ipepTmpRef = new IPEndPoint(IPAddress.Any, 0); ucRefSock = ReflectorMgr.Sockets.SockUCv4RTCP; mcSrvSock = ReflectorMgr.Sockets.SockMCv6RTCP; ucSrvSock = ReflectorMgr.Sockets.SockUCv6RTCP; break; case TrafficType.IPv4RTP: ucPort = ReflectorMgr.ReflectorUnicastRTPListenPort; mcPort = ReflectorMgr.ReflectorMulticastRTPListenPort; ipepTmpRef = new IPEndPoint(IPAddress.IPv6Any, 0); ipepTmpSrv = new IPEndPoint(IPAddress.Any, 0); ucRefSock = ReflectorMgr.Sockets.SockUCv6RTP; mcSrvSock = ReflectorMgr.Sockets.SockMCv4RTP; ucSrvSock = ReflectorMgr.Sockets.SockUCv4RTP; break; case TrafficType.IPv6RTP: ucPort = ReflectorMgr.ReflectorUnicastRTPListenPort; mcPort = ReflectorMgr.ReflectorMulticastRTPListenPort; ipepTmpSrv = new IPEndPoint(IPAddress.IPv6Any, 0); ipepTmpRef = new IPEndPoint(IPAddress.Any, 0); ucRefSock = ReflectorMgr.Sockets.SockUCv4RTP; mcSrvSock = ReflectorMgr.Sockets.SockMCv6RTP; ucSrvSock = ReflectorMgr.Sockets.SockUCv6RTP; break; default: Debug.Assert(false); throw new ArgumentException(Strings.InvalidTrafficTypeCombination); } #endregion IList <IPEndPoint> members = new List <IPEndPoint>(); byte[] buf = new byte[1500]; while (true) { try { EndPoint sourceEP = new IPEndPoint(IPAddress.Any, 0); IPPacketInformation ipPackInfo; SocketFlags flags = SocketFlags.None; size = mcSrvSock.ReceiveMessageFrom(buf, 0, buf.Length, ref flags, ref sourceEP, out ipPackInfo); IPEndPoint sourceIpe = (IPEndPoint)sourceEP; registrar.MarkIPAddressAsUsingMulticast(sourceIpe.Address); // If the packet's source address is the reflector's IP address then this packet // was forwarded from Unicast to Multicast by the reflector. So, we shouldn't // forward it to UC again. Also, "AND" this condition with source port // equal to 7004/7005 to have the support running the reflector and CXPClient on the // same machine. if ((sourceIpe.Port != ucPort) || (!sourceIpe.Address.Equals(ReflectorMgr.MulticastInterfaceIP) && !sourceIpe.Address.Equals(ReflectorMgr.IPv6MulticastInterfaceIP))) { if ((traffTypes & TrafficType.RTP) == TrafficType.RTP) { ReflectorMgr.PC[ReflectorPC.ID.MulticastPacketsReceivedOther]++; } // Lookup the members of this multicast group. IPEndPoint multicastEP = new IPEndPoint(ipPackInfo.Address, mcPort); registrar.MemberLookup(members, multicastEP); if (members.Count != 0) { // Send the data to each individual. for (int j = 0; j < members.Count; j++) { if (members[j].AddressFamily == ucSrvSock.AddressFamily) { ucSrvSock.SendTo(buf, 0, size, SocketFlags.None, members[j]); } else if ((ucRefSock != null) && (members[j].AddressFamily == ucRefSock.AddressFamily)) { ucRefSock.SendTo(buf, 0, size, SocketFlags.None, members[j]); } } if ((traffTypes & TrafficType.RTP) == TrafficType.RTP) { ReflectorMgr.PC[ReflectorPC.ID.MCtoUCPacketsSent] += members.Count; } } } else if ((traffTypes & TrafficType.RTP) == TrafficType.RTP) { ReflectorMgr.PC[ReflectorPC.ID.MulticastPacketsReceivedSelf]++; } } // On stopping the service, avoid the AbortException written in the event viewer catch (ThreadAbortException) {} catch (Exception e) // Connection reset by peer! this happens occasionally when a UC client leaves. { eventLog.WriteEntry(string.Format(CultureInfo.CurrentCulture, Strings.MCtoUCListenerException, traffTypes, e.ToString()), EventLogEntryType.Warning, (int)ReflectorEventLog.ID.MCtoUCException); } } }