/// <summary> /// Sends a join request to RegistrarServer and returns the confirmation number. This method opens /// a connection to the server sends a request message, receives a response message and closes the /// connection to the server. /// </summary> /// <param name="groupIP">The group IP address to join</param> /// <param name="groupPort">The group port number to join</param> /// <returns>The RTP unicast port</returns> public int join(IPAddress groupIP, int groupPort) { try { // Creating and initializing the network related objects. TcpClient tcpC = new TcpClient(regSrvIP.AddressFamily); tcpC.Connect(regSrvIP, regSrvPort); NetworkStream netStream = tcpC.GetStream(); BinaryFormatter bf = new BinaryFormatter(); joiningMulticastEP = new IPEndPoint(groupIP, groupPort); // Building the message to be sent to RegistrarServer (MessageType: Join) RegisterMessage regMsg = new RegisterMessage(MessageType.Join, groupIP, groupPort); // Sending the message request object to the RegistrarSErver bf.Serialize(netStream,regMsg); // Receiving the message response object from the RegistrarServer Object obj = bf.Deserialize(netStream); regMsg = (RegisterMessage) obj; // Closing the server connection. tcpC.Close(); // Saving the confirmation number and RTP unicast port refSrvCookie = regMsg.confirmNumber; return regMsg.unicastPort; } catch(Exception e) { eventLog.WriteEntry("Join request to server " + regSrvIP + ":" + regSrvPort + "for " + joiningMulticastEP + " failed. \n" + e.ToString(),System.Diagnostics.EventLogEntryType.Error, (int)RtpEL.ID.ReflectorJoinFailed); throw; } }
private static RegisterMessage ProcessLeaveRequest(RegisterMessage leaveRequestMessage, IPAddress senderIP) { try { lock (clientRegTable.SyncRoot) { if (clientRegTable.ContainsKey(senderIP)) { bool drop = true; clientRegTable.Remove(senderIP); ReflectorMgr.PC[ReflectorPC.ID.CurrentParticipats] = clientRegTable.Count; // Drop membership if no other member exists foreach (ClientEntry entry in clientRegTable.Values) { if (entry.GroupEP.Address.Equals(leaveRequestMessage.groupIP)) { drop = false; break; } } if (drop) { if (leaveRequestMessage.groupIP.AddressFamily == AddressFamily.InterNetwork) { MulticastOption mo = new MulticastOption(leaveRequestMessage.groupIP,ReflectorMgr.MulticastInterfaceIP); ReflectorMgr.Sockets.SockMCv4RTP.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.DropMembership, mo); ReflectorMgr.Sockets.SockMCv4RTCP.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.DropMembership, mo); } else { IPv6MulticastOption mo = new IPv6MulticastOption(leaveRequestMessage.groupIP); ReflectorMgr.Sockets.SockMCv6RTP.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.DropMembership, mo); ReflectorMgr.Sockets.SockMCv6RTCP.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.DropMembership, mo); } } return new RegisterMessage(MessageType.Confirm, leaveRequestMessage.groupIP, leaveRequestMessage.groupPort, leaveRequestMessage.confirmNumber); } else { // No entries found for the leave request return new RegisterMessage(MessageType.LeaveWithoutJoinError, IPAddress.Any); } } } catch { return new RegisterMessage(MessageType.UnknownError, IPAddress.Any); } }
private static RegisterMessage ProcessJoinRequest(RegisterMessage joinRequestMessage, IPAddress senderIP) { try { // If the senderIP already exists, remove it by following the rule - the last one wins if (clientRegTable.ContainsKey(senderIP)) { lock (clientRegTable.SyncRoot) { clientRegTable.Remove(senderIP); } } // Insert the new entry Random rnd = new Random(); int confirmNumber = rnd.Next(1, Int32.MaxValue); lock (clientRegTable.SyncRoot) { clientRegTable.Add(senderIP, new ClientEntry(senderIP, new IPEndPoint(joinRequestMessage.groupIP, joinRequestMessage.groupPort), DateTime.Now, confirmNumber, DateTime.Now)); ReflectorMgr.PC[ReflectorPC.ID.TotalParticipants]++; ReflectorMgr.PC[ReflectorPC.ID.CurrentParticipats] = clientRegTable.Count; } joinRequestMessage.msgType = MessageType.Confirm; joinRequestMessage.confirmNumber = confirmNumber; joinRequestMessage.unicastPort = ReflectorMgr.ReflectorUnicastRTPListenPort; if (joinRequestMessage.groupIP.AddressFamily == AddressFamily.InterNetwork) { MulticastOption mo = new MulticastOption(joinRequestMessage.groupIP,ReflectorMgr.MulticastInterfaceIP); ReflectorMgr.Sockets.SockMCv4RTP.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, mo); ReflectorMgr.Sockets.SockMCv4RTCP.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, mo); } else { IPv6MulticastOption mo = new IPv6MulticastOption(joinRequestMessage.groupIP); ReflectorMgr.Sockets.SockMCv6RTP.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.AddMembership, mo); ReflectorMgr.Sockets.SockMCv6RTCP.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.AddMembership, mo); } } catch { joinRequestMessage.msgType = MessageType.UnknownError; } return joinRequestMessage; }
/// <summary> /// Starts listening in an infinite loop for incomming connections from RegistrarClient. Here are the /// scenarios: /// Client Request Client Status in Table Table Action Server Response to Client /// ------------------- ---------------------- ------------ ------------------------- /// 1 Msg(Join,GIP,GP,N) (CIP, GIP, GP) entry NOT FOUND Insert Msg(Confirm,GIP,GP,RndConfirmNum) /// 2 Msg(Join,GIP,GP,N) (CIP, GIP, GP) entry FOUND None Msg(ReConfirm,GIP,GP,FoundConfirmNum) /// 3 Msg(Leave,GIP,GP,ConfirmNum) Entry Found ConirmNum match Delete Msg(Confirm,GIP,GP,FoundConfirmNum) /// 4 Msg(Leave,GIP,GP,ConfirmNum) Entry Found ConirmNum mismatch None Msg(ConfirmNumMismatchError,0,0,0) /// 5 Msg(Leave,GIP,GP,ConfirmNum) Entry Not Found None Msg(LeaveWithoutJoinError,0,0,0) /// 6 Msg(Leave,GIP,GP,ConfirmNum) Lookup Error None Msg(UnknownError,0,0,0) /// /// </summary> public void Start() { TrafficType traffTypes = TrafficType.None; if (idxRSThreadTypeData < ThreadTypeData.Length) { lock (ThreadTypeData) { traffTypes = ThreadTypeData[idxRSThreadTypeData]; System.Threading.Thread.CurrentThread.Name = "Reflector_RegistrarServer_" + traffTypes.ToString(); idxRSThreadTypeData++; } } else { throw new Exception("Number of created threads exceed the number of thread types defined."); } IPEndPoint localEP; if ((traffTypes & TrafficType.IPv6) == TrafficType.IPv6) { localEP = new IPEndPoint(IPAddress.IPv6Any,ReflectorMgr.RegistrarServerPort); } else { localEP = new IPEndPoint(IPAddress.Any,ReflectorMgr.RegistrarServerPort); } // Initializing the TCP server NetworkStream netStream; BinaryFormatter bf = new BinaryFormatter(); Object obj; RegisterMessage regMsg , regMsgResponse; // Initializing the TcpListener TcpListener tcpL = new TcpListener(localEP); if ((traffTypes & TrafficType.IPv6) == TrafficType.IPv6) { tcpLv6 = tcpL; } else { tcpLv4 = tcpL; } tcpL.Start(); Socket srvS = null; // An inifinite loop which works as follows: // 1. Block until a connection arrives. // 2. If it is a join request // Lookup (ClientIP,GroupIP,GroupPort) and send back Confirm or ReConfirm // 2. If it is a leave request // Lookup (ClientIP,GroupIP,GroupPort) and if exist send back Confirm or ConfirmNumMismatch // if not exist send back LeaveWithoutJoinError // if unknown error send back UnknownError // 2. If neither join nor leave // send back InvalidRequest // 3. Close the connection. // while (true) { try { srvS = tcpL.AcceptSocket(); // Can't use AcceptTcpClient since the client information is protected netStream = new NetworkStream(srvS, System.IO.FileAccess.ReadWrite, true); //Getting a network stream so I can serialize the class into it. // Getting the request Object from stream obj = bf.Deserialize(netStream); regMsg = (RegisterMessage) obj; eventLog.WriteEntry("RegistrarServer: Received Request:" + regMsg.ToString(), EventLogEntryType.Information, (int)ReflectorEventLog.ID.JoinLeave); switch (regMsg.msgType) { case MessageType.Join: // Processing Join Request regMsgResponse = ProcessJoinRequest(regMsg,((IPEndPoint)srvS.RemoteEndPoint).Address); break; case MessageType.Leave: // Processing Leave Request regMsgResponse = ProcessLeaveRequest(regMsg,((IPEndPoint)srvS.RemoteEndPoint).Address); break; default: // Invalid Message Type regMsgResponse = new RegisterMessage(MessageType.InvalidRequest, IPAddress.Any); break; } bf.Serialize(netStream, regMsgResponse); netStream.Close(); srvS.Close(); } // On stopping the service, avoid the AbortException written in the event viewer catch(ThreadAbortException){} catch (Exception e) { eventLog.WriteEntry("RegistrarServer: Network Error while receiving/sending request message. Client: " + ((srvS!=null)?((IPEndPoint) srvS.RemoteEndPoint).ToString():"") + " " + e.ToString(), EventLogEntryType.Error, (int)ReflectorEventLog.ID.Error); } } // end while }
public static void ForceLeave(ClientEntry client) { RegisterMessage leaveMessage = new RegisterMessage(MessageType.Leave, client.GroupEP.Address, client.GroupEP.Port, client.ConfirmNumber); ProcessLeaveRequest(leaveMessage, client.ClientIP); }
/// <summary> /// Sends a leave request to RegistrarServer for groupIP and groupPort. This method opens /// a connection to the server sends a request message, receives a response message and closes the /// connection to the server. /// </summary> /// <param name="groupIP">The group IP address to leave</param> /// <param name="groupPort">The group Port number to leave</param> /// <param name="confirmNumber">The confirmation number received from the RegistrarServer at the join time</param> public void leave() { try { // Creating and initializing the network related objects. TcpClient tcpC = new TcpClient(regSrvIP.AddressFamily); tcpC.Connect(regSrvIP, regSrvPort); NetworkStream netStream = tcpC.GetStream(); BinaryFormatter bf = new BinaryFormatter(); // Building the message to be sent to RegistrarServer (MessageType: Leave) RegisterMessage regMsg = new RegisterMessage(MessageType.Leave,joiningMulticastEP.Address, joiningMulticastEP.Port, refSrvCookie); // Sending the message request object to the RegistrarSErver bf.Serialize(netStream,regMsg); // Receiving the message response object from the RegistrarServer Object obj = bf.Deserialize(netStream); regMsg = (RegisterMessage) obj; // Closing the server connection tcpC.Close(); } catch (Exception e) { eventLog.WriteEntry(string.Format(CultureInfo.CurrentCulture, Strings.LeaveRequestToServerFailed, regSrvIP, regSrvPort, joiningMulticastEP, e.ToString()), System.Diagnostics.EventLogEntryType.Error, (int)RtpEL.ID.ReflectorJoinFailed); } }