protected override bool UpdateTarget( ReceiveContext context ) { using( Synchronizer.Lock( context.Model.SyncRoot ) ) { using( Synchronizer.Lock( context.Model.ViewerState.Diagnostic.SyncRoot ) ) context.Model.ViewerState.Diagnostic.ExecuteLocalScript = !context.Model.ViewerState.Diagnostic.ExecuteLocalScript; } return false; }
public CXPCapabilityMessageReceiver(CXPCapabilityMessageSender sender, uint ssrc, PresenterModel model, ClassroomModel classroom, ParticipantModel participant) { this.m_Model = model; this.m_Sender = sender; this.m_RemoteSSRC = ssrc; this.m_Context = new ReceiveContext(model, classroom, participant); this.m_ContextArgs = new object[] { this.m_Context }; this.m_Queue = new MessageProcessingQueue(this); this.m_Assembler = new ChunkAssembler(); this.m_Assembler.Nack += new ChunkAssembler.NackDelegate(this.HandleAssemblerNack); }
protected override bool UpdateTarget(ReceiveContext context) { // For the purposes of removal, whether the group is a Group or a SingletonGroup // doesn't matter; all that matters is the Guid. Group group = new Group(this.GroupId, this.FriendlyName); using (Synchronizer.Lock(context.Participant.SyncRoot)) { if (context.Participant.Groups.Contains(group)) context.Participant.Groups.Remove(group); } return false; }
protected override bool UpdateTarget( ReceiveContext context ) { using( Synchronizer.Lock( context.Model.SyncRoot ) ) { // Check if this message is meant for this client using( Synchronizer.Lock( context.Model.Participant.SyncRoot ) ) if( context.Model.Participant.Role is InstructorModel || context.Model.Participant.Role.Id != this.participantId ) return false; // Set Client Model Sync State using( Synchronizer.Lock( context.Model.ViewerState.Diagnostic.SyncRoot ) ) context.Model.ViewerState.Diagnostic.ClientState = DiagnosticModel.ClientSyncState.PINGING; } return false; }
public RTPMessageReceiver(RTPMessageSender sender, RtpStream stream, PresenterModel model, ClassroomModel classroom, ParticipantModel participant) { this.m_Model = model; this.m_Sender = sender; this.m_RtpStream = stream; this.m_Context = new ReceiveContext(model, classroom, participant); this.m_ContextArgs = new object[] { this.m_Context }; this.m_Queue = new MessageProcessingQueue(this); this.m_Serializer = new BinaryFormatter(); this.m_Assembler = new ChunkAssembler(); this.m_Assembler.Nack += new ChunkAssembler.NackDelegate(this.HandleAssemblerNack); this.m_RtpStream.FrameReceived += new RtpStream.FrameReceivedEventHandler(this.HandleFrameReceived); }
protected override bool UpdateTarget(ReceiveContext context) { // Discard bogus SingletonGroups. A participant cannot // belong to a SingletonGroup that does not match his Guid. if (this.Singleton && this.GroupId != context.Participant.Guid) return false; Group group = this.Singleton ? new SingletonGroup(context.Participant) : new Group(this.GroupId, this.FriendlyName); using (Synchronizer.Lock(context.Participant.SyncRoot)) { if (!context.Participant.Groups.Contains(group)) { context.Participant.Groups.Add(group); } } return false; }
protected override bool UpdateTarget(ReceiveContext context) { using (Synchronizer.Lock(context.Model.SyncRoot)) { // Ensure that this message is only handled by the correct student using (Synchronizer.Lock(context.Model.Participant.SyncRoot)) if (context.Model.Participant.Role is InstructorModel || context.Model.Participant.Role.Id != this.participantId) return false; // Set the Client Model Sync State and update the latency using (Synchronizer.Lock(context.Model.ViewerState.Diagnostic.SyncRoot)) { context.Model.ViewerState.Diagnostic.AddLatencyEntry(UW.ClassroomPresenter.Misc.AccurateTiming.Now); context.Model.ViewerState.Diagnostic.ClientState = DiagnosticModel.ClientSyncState.START; } } return false; }
protected override bool UpdateTarget( ReceiveContext context ) { using( Synchronizer.Lock( context.Model.SyncRoot ) ) { // Ensure that this message is only handled by the instructor using( Synchronizer.Lock( context.Model.Participant.SyncRoot ) ) if( !(context.Model.Participant.Role is InstructorModel) ) return false; // Set Server Model Sync State using( Synchronizer.Lock( context.Model.ViewerState.Diagnostic.SyncRoot ) ) context.Model.ViewerState.Diagnostic.ServerState = DiagnosticModel.ServerSyncState.PONGING; } return false; }
/// <summary> /// Enqueues a message for later execution on the message thread. /// If the message thread is busy, and other messages are already /// enqueued, the messages are combined (<see cref="Message.ZipInto"/>), /// which may help to avoid duplicating work in some situations. /// For example, multiple "Ink Erase" messages received in a row /// can be combined into a single message, which saves the UI work /// by only repainting itself once. /// </summary> /// <remarks> /// (In fact, there is no "queue" -- meaning a list of messages -- but /// rather the "zipped" messages provide all the functionality we need.) /// /// FIXME: If we zip messages from different remote nodes, we /// call OnReceive for all of them with the context of the last. /// /// </remarks> /// <param name="message">The message to execute</param> public void ProcessMessage(Message message,ReceiveContext context) { using (Synchronizer.Lock(this)) { if (this.m_Waiting == null) { this.m_Waiting = message; this.Post(delegate() { Message waited; using (Synchronizer.Lock(this)) { if (this.m_Waiting != null) { waited = this.m_Waiting; this.m_Waiting = null; } else { return; } } waited.OnReceive(context); }); } else { message.ZipInto(ref this.m_Waiting); } } }
/// <summary> /// Processes a message received over the TCP network interface. /// </summary> private void ReceiveThread() { while (true) { try { if (this.m_Disposed) return; object message = null; ReceiveMessageAndParticipant rm; rm = (ReceiveMessageAndParticipant)this.m_Receiver.Read(); //does not block. if (rm == null) { //probably because of empty receive queue Thread.Sleep(50); continue; } message = rm.Message; ReceiveContext context = new ReceiveContext(m_Model,m_Classroom,rm.Participant); // If the message is a chunked, process it with the Chunk Assembler. // (Messages don't have to be chunked, in which case they are processed // immediately below). If the chunk is the last remaining chunk composing // a message, then the Assembler returns the completed message. if (message is Chunk) { Chunk chunk = message as Chunk; try { Debug.WriteLine(string.Format("Received message #{0}, chunk #{1} of {2}, {3} bytes.", chunk.MessageSequence, chunk.ChunkSequenceInMessage + 1, chunk.NumberOfChunksInMessage, chunk.Data.Length), this.GetType().ToString()); message = this.m_Assembler.Add((Chunk)message); } catch (Exception e) { Trace.WriteLine(string.Format("Error deserializing a message from message #{0}, chunk #{1} of {2} ({3} bytes): {4}", chunk.MessageSequence, chunk.ChunkSequenceInMessage + 1, chunk.NumberOfChunksInMessage, chunk.Data.Length, e.ToString()), this.GetType().ToString()); continue; } } // If we have a valid/complete message, queue it for processing on the separate // message execution thread. if (message is IEnumerable<object>) { foreach (object decoded in (IEnumerable<object>)message) { if (decoded is Message) { Message m = (Message)decoded; this.m_Model.ViewerState.Diagnostic.LogMessageRecv(m); //Debug.WriteLine(string.Format("Received message: {0} bytes, type {1}", // "???", m.GetType()), this.GetType().ToString()); Debug.WriteLine("Received message:" + m.ToString(),"TCPMessageReceiver"); //If enabled, do client-slide bridging #if RTP_BUILD if (this.m_U2MBridge != null) { this.m_U2MBridge.SendToBridge(m.Clone()); } #endif // Send it off for processing. this.m_Queue.ProcessMessage(m, context); } else if (decoded != null) { Trace.WriteLine("Received unknown message type: " + decoded.GetType().ToString(), this.GetType().ToString()); } } } else if (message != null) { Trace.WriteLine("Received unknown message type: " + message.GetType().ToString(), this.GetType().ToString()); } } catch (Exception e) { // The application should not crash on account of malformed messages sent from remote clients. // Therefore, we catch all exceptions. We only want to print an error message. Trace.WriteLine("Error processing a message: " + e.ToString(), this.GetType().ToString()); } } }