public TCPClient(IPEndPoint remoteEP, ParticipantModel participant, NetworkModel network, Guid serverID) { m_Connected = false; m_Network = network; m_Participant = participant; m_LastMsgReceived = DateTime.MaxValue; m_ServerId = serverID; m_ClientTimeout = TimeSpan.FromMilliseconds(TCP_HEARTBEAT_TIMEOUT_DEFAULT_MS); this.m_RemoteEP = remoteEP; m_Socket = null; m_ServerParticipant = null; m_ReceiveQueue = new Queue(); this.m_Encoder = new Chunk.ChunkEncoder(); m_NetworkStatus = new NetworkStatus(ConnectionStatus.Disconnected, ConnectionProtocolType.TCP, TCPRole.Client, 0); this.m_Network.RegisterNetworkStatusProvider(this, true, m_NetworkStatus); //Find out if client-side bridging is enabled m_BridgeEnabled = false; string enableBridge = System.Configuration.ConfigurationManager.AppSettings[this.GetType().ToString() + ".EnableBridge"]; if (enableBridge != null) { bool enable = false; if (bool.TryParse(enableBridge, out enable)) { Trace.WriteLine("Unicast to Multicast Bridge enabled=" + enable.ToString(), this.GetType().ToString()); m_BridgeEnabled = enable; } } }
public TCPServer(IPEndPoint localEP, PresenterModel model, ClassroomModel classroom, InstructorModel instructor) { string portStr = System.Configuration.ConfigurationManager.AppSettings[this.GetType().ToString() + ".TCPListenPort"]; int p; if (Int32.TryParse(portStr, out p)) { TCPListenPort = p; } RestoreConfig(); m_ClientConnected = new ManualResetEvent(false); m_Participant = model.Participant; m_Classroom = classroom; m_ClientCount = 0; this.m_Network = model.Network; m_NetworkStatus = new NetworkStatus(ConnectionStatus.Disconnected, ConnectionProtocolType.TCP, TCPRole.Server, 0); this.m_Network.RegisterNetworkStatusProvider(this, true, m_NetworkStatus); if (localEP != null) { this.m_ListenEP = localEP; } else { IPAddress ip = IPAddress.Any; //Use IPv4 unless it is unavailable. TODO: Maybe this should be a configurable parameter? if ((!Socket.OSSupportsIPv4) && (Socket.OSSupportsIPv6)) { ip = IPAddress.IPv6Any; } this.m_ListenEP = new IPEndPoint(ip, TCPListenPort); } m_AllClients = new Hashtable(); m_ReceiveQueue = new Queue(); this.m_Encoder = new Chunk.ChunkEncoder(); this.m_ServerSender = new TCPServerSender(instructor); //Start bridging if config file says so #if RTP_BUILD m_U2MBridge = null; string enableBridge = System.Configuration.ConfigurationManager.AppSettings[this.GetType().ToString() + ".EnableBridge"]; if (enableBridge != null) { bool enable = false; if (bool.TryParse(enableBridge, out enable) && enable) { Trace.WriteLine("Unicast to Multicast Bridge enabled.", this.GetType().ToString()); m_U2MBridge = new UnicastToMulticastBridge(model); } } #endif }
public UnicastToMulticastBridge(PresenterModel model) { GetConfig(); //Prepare for RTP sending m_RtpParticipant = new RtpParticipant(m_Cname, m_Name); try { m_RtpSession = new RtpSession(m_MulticastEndpoint, m_RtpParticipant, true, false); } catch (Exception e) { Trace.WriteLine(e.ToString()); m_RtpSession = null; m_RtpParticipant = null; return; } try { /// Notes about FEC: There are two types supported by the MSR RTP stack: Frame-based and Packet-based. /// Setting cDataPx to zero forces frame-based. In this case cFecPx is a percentage. It must be greater than zero, but can be /// very large, eg. 1000. Frame-based FEC appears to be better for large frames (which the stack splits into multiple packets) /// possibly because the FEC packets for the frame are not interlaced in time sequence with the frame packets. /// If cDataPx is not zero, packet-based FEC is used. In this mode cDataPx and cFecPx are a ratio of data packets to fec packets. /// For single packet frames, 1:1 and 0:100 are identical. Single packet frames are frames smaller than /// the MTU which is normally 1500 bytes. Presenter's Chunk encoder creates frames up to 16kbytes. Many frames are smaller /// than this, but only a few are below the MTU. For this reason we will always use Frame-based FEC. Usful values are expected to /// be from around 10 up to around 100. More than 100 might be good in some cases, but might impact performance. /// More than 500 would probably never be advised. m_RtpSender = m_RtpSession.CreateRtpSenderFec("Classroom Presenter Unicast to Multicast Bridge", PayloadType.dynamicPresentation, null, 0, m_Fec); m_RtpSender.DelayBetweenPackets = m_InterpacketDelay; } catch (Exception e) { Trace.WriteLine(e.ToString()); try { m_RtpSession.Dispose(); } catch { } m_RtpParticipant = null; m_RtpSession = null; m_RtpSender = null; return; } //Prepare the beacon this.m_ChunkSequence = 0; this.m_Encoder = new Chunk.ChunkEncoder(); this.m_BeaconService = new Beacons.BridgeBeaconService(this, model); //Prepare the queue and sending thread m_Disposing = false; m_SendQueueWait = new EventWaitHandle(false, EventResetMode.AutoReset); m_SendQueue = new PriorityQueue <BridgeMessage>(); m_SendThread = new Thread(new ThreadStart(SendThread)); m_SendThread.Start(); }
public ClientUnicastToMulticastBridge(PresenterModel model) : base(model) { m_Disposing = false; this.m_ChunkSequence = 0; this.m_Encoder = new Chunk.ChunkEncoder(); //make a queue and a thread m_SendQueueWait = new EventWaitHandle(false, EventResetMode.AutoReset); m_SendQueue = new Queue <ChunksAndPriority>(); m_SendThread = new Thread(new ThreadStart(SendThread)); m_SendThread.Start(); }
public CXPCapabilityMessageSender(PresenterModel model, PresenterCapability capability) { this.m_Model = model; this.m_LocalId = m_Model.Participant.Guid; this.m_Classroom = new ClassroomModel(null, "CXP Capability Classroom", ClassroomModelType.CXPCapability); this.m_Capability = capability; this.m_Participants = new Dictionary <string, ParticipantModel>(); this.m_SsrcToSenderId = new Dictionary <uint, Guid>(); this.m_Receivers = new Dictionary <string, CXPCapabilityMessageReceiver>(); m_Capability.OnStreamAdded += new PresenterCapability.OnStreamAddedHandler(OnStreamAdded); m_Capability.OnStreamRemoved += new PresenterCapability.OnStreamRemovedHandler(OnStreamRemoved); using (Synchronizer.Lock(this)) { // Initialize the message chunking utilities. this.m_Encoder = new Chunk.ChunkEncoder(); // TODO: Make the buffer size dynamic, ie., grow if we send a single very large message. // Make the buffer store up to 5MB worth of data. this.m_FrameBuffer = new FrameBuffer(5 * 1024 * 1024 / this.m_Encoder.MaximumChunkSize); // Create the NackManager which is responsible for sending NACKs on behalf of // our set of RTPMessageReceivers. this.m_NackManager = new RTPNackManager(this, this.m_Classroom); } // Create network services outside of the "lock(this)" so they can lock their own objects // without worrying about locking order. // Create the PresenterNetworkService which will watch for changes to the model and send messages. this.m_PresenterNetworkService = new PresenterNetworkService(this, this.m_Model); // Create the StudentSubmissionsNetworkService which will watch for requests to submit and send messages. this.m_StudentSubmissionNetworkService = new StudentSubmissionNetworkService(this, this.m_Model); // Create the SynchronizationNetworkService which will watch for all synchronization messages. this.m_SynchronizationNetworkService = new SynchronizationNetworkService(this, this.m_Model); // Create the ScriptingNetworkService which will watch for all scripting messages. this.m_ScriptingNetworkService = new ScriptingNetworkService(this, this.m_Model); // Create the BeaconService which will broadcast periodic information about the presentation. this.m_BeaconService = new Beacons.DefaultBeaconService(this, this.m_Model); // Report Network status to the UI m_CapabilityNetworkStatus = new CapabilityNetworkStatus(this.m_Model); m_CapabilityNetworkStatus.Register(); // Send an initial message to announce our node to others in the venue. SendObject(new CapabilityMessageWrapper(null, m_LocalId, Guid.Empty, m_Capability.IsSender)); }
public TCPMessageSender(ITCPSender server, PresenterModel model, ClassroomModel classroom) { this.m_Model = model; this.m_Classroom = classroom; this.m_Sender = server; // Initialize the message chunking utilities. this.m_Encoder = new Chunk.ChunkEncoder(); // Most of the same services are created as in RTPMessageSender, with the exception // (for now, at least) that there is no BeaconService. // Create the PresenterNetworkService which will watch for changes to the model and send messages. this.m_PresenterNetworkService = new PresenterNetworkService(this, this.m_Model); // Create the StudentSubmissionsNetworkService which will watch for requests to submit and send messages. this.m_StudentSubmissionNetworkService = new StudentSubmissionNetworkService(this, this.m_Model); // Create the SynchronizationNetworkService which will watch for all synchronization messages. //this.m_SynchronizationNetworkService = new SynchronizationNetworkService(this, this.m_Model); // Create the ScriptingNetworkService which will watch for all scripting messages. //this.m_ScriptingNetworkService = new ScriptingNetworkService(this, this.m_Model); }
public RTPMessageSender(IPEndPoint ep, PresenterModel model, ClassroomModel classroom) { this.m_Model = model; this.m_Classroom = classroom; this.m_RtpLocalParticipant = new RtpLocalParticipant(this.m_Model.Participant); using (Synchronizer.Lock(this)) { // Register the stream event listeners first, since otherwise there would be a chance // that streams could be added between creating the RtpSession (which connects immediately). this.m_ParticipantManager = new ParticipantManager(this); this.m_RtpSession = new RtpSession(ep, this.m_RtpLocalParticipant, true, true); // TODO: Choose a meaningful value for the RtpSender name. ushort fec; short interpacketdelay; using (Synchronizer.Lock(model.SyncRoot)) { using (Synchronizer.Lock(model.ViewerState.SyncRoot)) { fec = (ushort)model.ViewerState.ForwardErrorCorrection; interpacketdelay = (short)model.ViewerState.InterPacketDelay; } } if (fec == 0) { this.m_RtpSender = this.m_RtpSession.CreateRtpSender("Classroom Presenter", PayloadType.dynamicPresentation, null); } else { this.m_RtpSender = this.m_RtpSession.CreateRtpSenderFec("Classroom Presenter", PayloadType.dynamicPresentation, null, 0, fec); } this.m_RtpSender.DelayBetweenPackets = interpacketdelay; // Initialize the message chunking utilities. this.m_Encoder = new Chunk.ChunkEncoder(); // TODO: Make the buffer size dynamic, ie., grow if we send a single very large message. // Make the buffer store up to 5MB worth of data. this.m_FrameBuffer = new FrameBuffer(5 * 1024 * 1024 / this.m_Encoder.MaximumChunkSize); // Create the NackManager which is responsible for sending NACKs on behalf of // our set of RTPMessageReceivers. this.m_NackManager = new RTPNackManager(this, this.m_Classroom); } // Create network services outside of the "lock(this)" so they can lock their own objects // without worrying about locking order. // Create the PresenterNetworkService which will watch for changes to the model and send messages. this.m_PresenterNetworkService = new PresenterNetworkService(this, this.m_Model); // Create the StudentSubmissionsNetworkService which will watch for requests to submit and send messages. this.m_StudentSubmissionNetworkService = new StudentSubmissionNetworkService(this, this.m_Model); // Create the SynchronizationNetworkService which will watch for all synchronization messages. this.m_SynchronizationNetworkService = new SynchronizationNetworkService(this, this.m_Model); // Create the ScriptingNetworkService which will watch for all scripting messages. this.m_ScriptingNetworkService = new ScriptingNetworkService(this, this.m_Model); // Create the BeaconService which will broadcast periodic information about the presentation. this.m_BeaconService = new Beacons.DefaultBeaconService(this, this.m_Model); }