コード例 #1
0
        //Construct
        public VersionExchange(ParticipantModel participant)
        {
            m_RemoteParticipant = participant;

            //Check local role
            using (Synchronizer.Lock(PresenterModel.TheInstance.Participant.SyncRoot)) {
                if (PresenterModel.TheInstance.Participant.Role is InstructorModel)
                {
                    this.m_LocalNodeIsInstructor = true;
                }
            }

            //Check and subscribe for changes to remote role
            using (Synchronizer.Lock(m_RemoteParticipant.SyncRoot)) {
                m_RemoteHumanName = m_RemoteParticipant.HumanName;
                if (m_RemoteParticipant.Role is InstructorModel)
                {
                    m_RemoteNodeIsInstructor = true;
                }
                m_RemoteParticipant.Changed["Role"].Add(new PropertyEventHandler(RoleChangedHandler));
            }


            //Flag instructor nodes to initiate the exchange by sending the request message.
            if (m_LocalNodeIsInstructor)
            {
                m_SendRequest = true;
            }
        }
コード例 #2
0
        /// <summary>
        /// Called when a VersionRequestMessage is received
        /// </summary>
        /// <param name="remoteParticipant"></param>
        /// <param name="version"></param>
        public void ReceiveVersionRequest(ParticipantModel remoteParticipant, VersionRequestMessage requestMessage)
        {
            Trace.WriteLine("VersionExchangeModel.ReceiveVersionRequest started. remoteParticipant=" +
                            remoteParticipant.Guid.ToString() + "; requesterID= " + requestMessage.RequesterId.ToString());
            VersionExchange ve;

            //Make a VersionExchange object if needed.
            using (Synchronizer.Lock(this.SyncRoot)) {
                if (m_VersionExchangeDictionary.ContainsKey(remoteParticipant.Guid))
                {
                    ve = m_VersionExchangeDictionary[remoteParticipant.Guid];
                }
                else
                {
                    //This probably should not happen, but if it does we are covered.
                    ve = new VersionExchange(remoteParticipant);
                    m_VersionExchangeDictionary.Add(remoteParticipant.Guid, ve);
                    m_VersionExchanges.Add(ve);
                    Trace.WriteLine("Created a VersionExchange in response to Version Request from participant: " + remoteParticipant.Guid.ToString());
                }
            }

            //Let the VersionExchange object process the inbound message
            ve.ReceiveRequest(requestMessage.RequesterVersion);
        }
コード例 #3
0
 public RoleSynchronizer(SlideViewer sv, ParticipantModel pm)
 {
     this.m_SlideViewer = sv;
     this.m_Participant = pm;
     this.m_Participant.Changed["Role"].Add(new PropertyEventHandler(this.onRoleChange));
     this.onRoleChange(this, null);
 }
コード例 #4
0
        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;
                }
            }
        }
コード例 #5
0
 /// <summary>
 /// Removes the specified <see cref="ParticipantModel"/> from the collection, if present.
 /// </summary>
 public void Remove(ParticipantModel value)
 {
     List.Remove(value);
     if (PresenterModel.TheInstance != null)
     {
         PresenterModel.TheInstance.VersionExchange.RemoveVersionExchange(value);
     }
 }
コード例 #6
0
 public ClientData(Socket s, Guid id, ParticipantModel part)
 {
     Socket = s;
     Id = id;
     Participant = part;
     ConnectionState = ConnectionState.Connected;
     Timeout = DateTime.MaxValue;
 }
コード例 #7
0
 public TCPHandshakeMessage(ParticipantModel participant, IPEndPoint ep)
 {
     this.ParticipantId = participant.Guid;
     this.EndPoint = ep;
     using (Synchronizer.Lock(participant.SyncRoot)) {
         this.HumanName = participant.HumanName;
     }
     LastMessageSequence = LastChunkSequence = 0;
 }
コード例 #8
0
        public RtpLocalParticipant(ParticipantModel participant)
            : base(participant.Guid.ToString(), null)
        {
            this.m_Participant = participant;

            // Enable broadcast of the application name and version.
            this.SetTool(true);

            this.m_Participant.Changed["HumanName"].Add(new PropertyEventHandler(this.HandleHumanNameChanged));
            this.HandleHumanNameChanged(this, null);
        }
コード例 #9
0
 public PresentationModel(Guid id, ParticipantModel owner, string humanName, bool isUntitledPresentation)
 {
     this.m_Id = id;
     this.m_DeckTraversals = new DeckTraversalCollection(this, "DeckTraversals");
     this.m_Participants = new ParticipantCollection(this, "Participants");
     this.m_Owner = owner;
     this.m_HumanName = humanName;
     this.m_QuickPoll = null;
     this.m_IsUntitledPresentation = isUntitledPresentation;
     CurrentPresentation = this;
 }
コード例 #10
0
        public ParticipantNetworkService(SendingQueue sender, PresenterModel model, ParticipantModel participant)
        {
            this.m_Sender = sender;
            this.m_Model = model;
            this.m_Participant = participant;

            this.m_RoleChangedDispatcher = new EventQueue.PropertyEventDispatcher(this.m_Sender, new PropertyEventHandler(this.HandleRoleChanged));
            this.m_Participant.Changed["Role"].Add(this.m_RoleChangedDispatcher.Dispatcher);
            this.m_RoleChangedDispatcher.Dispatcher(this, null);

            this.m_GroupCollectionHelper = new GroupCollectionHelper(this);
        }
コード例 #11
0
        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);
        }
コード例 #12
0
        /// <summary>
        /// When a participant is removed from a classroom, clean up the version exchange
        /// </summary>
        /// <param name="value"></param>
        internal void RemoveVersionExchange(ParticipantModel participant)
        {
            if ((participant.Guid.Equals(Guid.Empty)) ||
                (participant.Guid.Equals(PresenterModel.ParticipantId)) ||
                (!m_VersionExchangeDictionary.ContainsKey(participant.Guid)))
            {
                return;
            }

            using (Synchronizer.Lock(this.SyncRoot)) {
                Trace.WriteLine("Removing VersionExchange for participant: " + participant.Guid.ToString());
                VersionExchange ve = m_VersionExchangeDictionary[participant.Guid];
                m_VersionExchanges.Remove(ve);
                m_VersionExchangeDictionary.Remove(participant.Guid);
            }
        }
コード例 #13
0
        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);
        }
コード例 #14
0
 public PresenterModel()
 {
     this.m_Stylus = null;
     this.m_CurrentResult = null;
     this.m_Network = new NetworkModel();
     this.m_VersionExchange = new VersionExchangeModel();
     /// Note: We currently assume that the ParticipantModel Guid will be different for each application invocation.
     /// (In particular TCP reconnection relies on this assumption.)  If we need an identifer that persists across
     /// sessions, we'd need to create a new identifier for this.
     ParticipantId = Guid.NewGuid();
     this.m_Participant = new ParticipantModel(ParticipantId, System.Windows.Forms.SystemInformation.UserName);
     this.m_Workspace = new WorkspaceModel();
     this.m_Undo = new UndoModel();
     this.m_ViewerState = new ViewerStateModel();
     this.m_PenState = new PenStateModel();
     TheInstance = this;
 }
コード例 #15
0
 /// <summary>
 /// If the participant is not identical to the local node, does not have a Guid.Empty identifier, and
 /// and if a VersionExchange has not already been created, create one here.  In some cases
 /// (notably if the local node is an instructor) this will cause the exchange to begin.
 /// </summary>
 /// <param name="participant"></param>
 public void CreateVersionExchange(ParticipantModel participant)
 {
     if ((participant.Guid.Equals(Guid.Empty)) ||
         (participant.Guid.Equals(PresenterModel.ParticipantId)) ||
         (m_VersionExchangeDictionary.ContainsKey(participant.Guid)))
     {
         return;
     }
     using (Synchronizer.Lock(this.SyncRoot)) {
         if (!m_VersionExchangeDictionary.ContainsKey(participant.Guid))
         {
             VersionExchange ve = new VersionExchange(participant);
             m_VersionExchangeDictionary.Add(participant.Guid, ve);
             //Adding to the collection here triggers an event in the corresponding Network Service
             m_VersionExchanges.Add(ve);
         }
     }
 }
コード例 #16
0
        private void SetNetworkAssociation(ParticipantModel participant)
        {
            // Remove any old event listeners.
            if (this.m_NetworkAssociation != null)
            {
                this.m_NetworkAssociation.Changed["Role"].Remove(this.m_NetworkAssociationRoleChangedDispatcher.Dispatcher);
            }

            this.m_NetworkAssociation = participant;

            // Watch for changes to the participant's Role, so we can know if/when we're associated with an Instructor.
            if (this.m_NetworkAssociation != null)
            {
                this.m_NetworkAssociation.Changed["Role"].Add(this.m_NetworkAssociationRoleChangedDispatcher.Dispatcher);
                this.m_NetworkAssociationRoleChangedDispatcher.Dispatcher(this, null);
            }
            else
            {
                this.SetNetworkAssociationRole(null);
            }
        }
コード例 #17
0
        /// <summary>
        /// Called when a VersionResponseMessage is received
        /// </summary>
        /// <param name="participantModel"></param>
        /// <param name="versionResponseMessage"></param>
        internal void ReceiveVersionResponse(ParticipantModel remoteParticipant, VersionResponseMessage versionResponseMessage)
        {
            Trace.WriteLine("VersionExchangeModel.ReceiveVersionResponse started. remoteParticipant=" +
                            remoteParticipant.Guid.ToString() + ";responderID=" + versionResponseMessage.ResponderId.ToString());

            VersionExchange ve = null;

            //Look up the VersionExchange for this remote participant
            using (Synchronizer.Lock(this.SyncRoot)) {
                if (m_VersionExchangeDictionary.ContainsKey(versionResponseMessage.ResponderId))
                {
                    ve = m_VersionExchangeDictionary[versionResponseMessage.ResponderId];
                }
            }
            //Let the VersionExchange handle the inbound message.
            if (ve != null)
            {
                ve.ReceiveResponse(versionResponseMessage);
            }
            else
            {
                Trace.WriteLine("Warning: Failed to find a pending version exchange to match inbound response message from participant: " + remoteParticipant.Guid.ToString());
            }
        }
コード例 #18
0
        private void SetNetworkAssociation(ParticipantModel participant)
        {
            // Remove any old event listeners.
            if (this.m_NetworkAssociation != null) {
                this.m_NetworkAssociation.Changed["Role"].Remove(this.m_NetworkAssociationRoleChangedDispatcher.Dispatcher);
            }

            this.m_NetworkAssociation = participant;

            // Watch for changes to the participant's Role, so we can know if/when we're associated with an Instructor.
            if (this.m_NetworkAssociation != null) {
                this.m_NetworkAssociation.Changed["Role"].Add(this.m_NetworkAssociationRoleChangedDispatcher.Dispatcher);
                this.m_NetworkAssociationRoleChangedDispatcher.Dispatcher(this, null);
            } else {
                this.SetNetworkAssociationRole(null);
            }
        }
コード例 #19
0
 /// <summary>
 /// Check to see if the given ParticipantModel is contained in the collection
 /// </summary>
 /// <param name="value">The ParticipantModel to check for</param>
 /// <returns>Returns true if the collection contains the ParticipantModel, false otherwise</returns>
 public bool Contains( ParticipantModel value )
 {
     return List.Contains(value);
 }
コード例 #20
0
 /// <summary>
 /// Constructor for the PresentationModel
 /// </summary>
 /// <param name="id">The unique identifier for this presentation</param>
 /// <param name="owner">The ParticipantModel of the owner of this presentation</param>
 public PresentationModel(Guid id, ParticipantModel owner)
     : this(id, owner, null,true)
 {
 }
コード例 #21
0
        /*
              public void HandleEnabledOnRoleChange(object sender, PropertyEventArgs args)
                  {
                  using(Synchronizer.Lock(this.m_Model.ViewerState.SyncRoot))
                      {
                  switch(this.m_Model.ViewerState.iRole)
                      {
                          //Natalie - figure out a
                      case 0: //Disconnected
                          this.Association = null;
                      case 1: //Viewer
                      case 2: //Presenter
                          this.Association = nulll;
                      case 3: //Public Display
                      }
                      }
                  HandleEnabled();
                  }
              */
        public void HandleEnabledAndAssociation(ParticipantModel association)
        {
            /*if (this.InvokeRequired)
                {
                this.Invoke(new HandleEnabledDelegate(HandleEnabled));
                }
            else
                {
                HandleEnabled();
                }
            */

            this.Enabled = false;
            this.Association = association;
            HandleEnabled();
        }
コード例 #22
0
        /// <summary>
        /// Called when a VersionResponseMessage is received
        /// </summary>
        /// <param name="participantModel"></param>
        /// <param name="versionResponseMessage"></param>
        internal void ReceiveVersionResponse(ParticipantModel remoteParticipant, VersionResponseMessage versionResponseMessage)
        {
            Trace.WriteLine("VersionExchangeModel.ReceiveVersionResponse started. remoteParticipant=" +
                remoteParticipant.Guid.ToString() + ";responderID=" + versionResponseMessage.ResponderId.ToString());

            VersionExchange ve = null;
            //Look up the VersionExchange for this remote participant
            using (Synchronizer.Lock(this.SyncRoot)) {
                if (m_VersionExchangeDictionary.ContainsKey(versionResponseMessage.ResponderId)) {
                    ve = m_VersionExchangeDictionary[versionResponseMessage.ResponderId];
                }
            }
            //Let the VersionExchange handle the inbound message.
            if (ve != null) {
                ve.ReceiveResponse(versionResponseMessage);
            }
            else {
                Trace.WriteLine("Warning: Failed to find a pending version exchange to match inbound response message from participant: " + remoteParticipant.Guid.ToString());
            }
        }
コード例 #23
0
 /// <summary>
 /// If the participant is not identical to the local node, does not have a Guid.Empty identifier, and
 /// and if a VersionExchange has not already been created, create one here.  In some cases 
 /// (notably if the local node is an instructor) this will cause the exchange to begin.
 /// </summary>
 /// <param name="participant"></param>
 public void CreateVersionExchange(ParticipantModel participant)
 {
     if ((participant.Guid.Equals(Guid.Empty)) ||
         (participant.Guid.Equals(PresenterModel.ParticipantId)) ||
         (m_VersionExchangeDictionary.ContainsKey(participant.Guid))) {
         return;
     }
     using (Synchronizer.Lock(this.SyncRoot)) {
         if (!m_VersionExchangeDictionary.ContainsKey(participant.Guid)) {
             VersionExchange ve = new VersionExchange(participant);
             m_VersionExchangeDictionary.Add(participant.Guid, ve);
             //Adding to the collection here triggers an event in the corresponding Network Service
             m_VersionExchanges.Add(ve);
         }
     }
 }
コード例 #24
0
 /// <summary>
 /// Inserts a <see cref="ParticipantModel"/> object into the collection at the specified index.
 /// </summary>
 public void Insert(int index, ParticipantModel value)
 {
     List.Insert(index, value);
 }
コード例 #25
0
 /// <summary>
 /// Adds a <see cref="ParticipantModel"/> object to the collection.
 /// </summary>
 /// <remarks>
 /// This method should not be used except by a <c>ConnectionManager</c>.
 /// </remarks>
 public int Add(ParticipantModel value)
 {
     return(List.Add(value));
 }
コード例 #26
0
 /// <summary>
 /// Retrieves the location of the specified <see cref="ParticipantModel"/> object in the collection.
 /// </summary>
 public int IndexOf(ParticipantModel value)
 {
     return(List.IndexOf(value));
 }
コード例 #27
0
 /// <summary>
 /// Inserts a ParticipantModel into the given index in the collection
 /// </summary>
 /// <param name="index">The index to insert into</param>
 /// <param name="value">The ParticipantModel to insert</param>
 public void Insert( int index, ParticipantModel value )
 {
     List.Insert(index, value);
 }
コード例 #28
0
        /// <summary>
        /// Maintain the connection to the server endpoint.
        /// </summary>
        private void ConnectThread()
        {
            while (!m_Disposed) {
                if ((m_Socket == null) || (!m_Socket.Connected) || (!m_Connected)) {
                    Socket s = (Socket)Interlocked.Exchange(ref m_Socket, null);
                    if (s != null) {
                        s.Close();
                    }

                    try {
                        if (m_Disposed) break;
                        using (Synchronizer.Lock(this.SyncRoot)) {
                            this.SetPublishedProperty("Connected", ref this.m_Connected, false);
                            NetworkStatus newStatus = m_NetworkStatus.Clone();
                            newStatus.ConnectionStatus = ConnectionStatus.TryingToConnect;
                            this.SetPublishedProperty("NetworkStatus", ref m_NetworkStatus, newStatus);
                        }
                        Trace.WriteLine("Attempting connection to server.", this.GetType().ToString());
                        m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                        m_Socket.ReceiveTimeout = 20000; //Temporarily set to 20 seconds for the handshaking phase.
                        //In case the server endpoint changed:
                        UpdateRemoteEndpoint();
                        m_Socket.Connect(this.m_RemoteEP);
                        m_NetworkStream = new NetworkStream(m_Socket); //NetworkStream does not own the socket.

                        //Receive handshake
                        BinaryFormatter bf = new BinaryFormatter();
                        object o = bf.Deserialize(m_NetworkStream);
                        if (o is TCPHandshakeMessage) {
                            Trace.WriteLine("Handshake received from " + ((TCPHandshakeMessage)o).ParticipantId.ToString() + " ep=" + ((TCPHandshakeMessage)o).EndPoint.ToString());
                            //send a handshake
                            TCPHandshakeMessage handshake = new TCPHandshakeMessage(m_Participant, (IPEndPoint)m_Socket.LocalEndPoint);
                            lock (this.m_ReceiveQueue) {
                                //If this is a reconnect, these values tell the server where we left off
                                handshake.LastMessageSequence = m_LastMsgSequence;
                                handshake.LastChunkSequence = m_LastChunkSequence;
                            }
                            MemoryStream ms = new MemoryStream();
                            bf.Serialize(ms, handshake);
                            m_NetworkStream.Write(ms.GetBuffer(), 0, (int)ms.Length);
                            Trace.WriteLine("Handshake sent.", this.GetType().ToString());
                            //The first time we connect to a server we create a new ParticipantModel to represent the server.
                            if (m_ServerParticipant == null) {
                                TCPHandshakeMessage h = (TCPHandshakeMessage)o;
                                m_ServerId = h.ParticipantId;
                                m_ServerParticipant = new ParticipantModel(m_ServerId, h.HumanName);
                            }
                            else {
                                //In reconnect scenarios we keep the same server ParticipantModel, but the Guid could
                                //change if the server was restarted.  In this case we just want to update the Guid.
                                //Notice that we can't create a new ParticipantModel here without breaking some things.
                                if (!m_ServerId.Equals(((TCPHandshakeMessage)o).ParticipantId)) {
                                    m_ServerId = ((TCPHandshakeMessage)o).ParticipantId;
                                    m_ServerParticipant.Guid = m_ServerId;
                                }
                            }
                        }
                        else {
                            throw new ApplicationException("Invalid handshake received: " + o.GetType().ToString());
                        }

                        m_Socket.ReceiveTimeout = 0; //Reset socket to infinite timeout.
                        m_ClientTimeout = SetClientTimeout();

                        using (Synchronizer.Lock(this.SyncRoot)) {
                            //Setting this property allows the ReceiveThread to begin:
                            this.SetPublishedProperty("Connected", ref this.m_Connected, true);
                            NetworkStatus newStatus = m_NetworkStatus.Clone();
                            newStatus.ConnectionStatus = ConnectionStatus.Connected;
                            this.SetPublishedProperty("NetworkStatus", ref m_NetworkStatus, newStatus);
                        }

                        lock (this.m_ReceiveQueue) {
                            //This enables the client timeout:
                            this.m_LastMsgReceived = DateTime.Now;
                        }

                        Trace.WriteLine("Connected.", this.GetType().ToString());
                    }
                    catch (SocketException se) {
                        if (se.ErrorCode == 10060) {
                            Trace.WriteLine("ConnectThread SocketException 10060: remote host failed to respond.");
                        }
                        else if (se.ErrorCode == 10038) {
                            Trace.WriteLine("ConnectThread SocketException 10038: operation attempted on non-socket.");
                        }
                        else {
                            Trace.WriteLine("ConnectThread SocketException " + se.ErrorCode.ToString() + ": " + se.Message);
                        }
                    }
                    catch (IOException ioe) {
                        Trace.WriteLine("ConnectThread IOException: " + ioe.Message);
                        if ((ioe.InnerException != null) && (ioe.InnerException is SocketException)) {
                            Trace.WriteLine("  InnerException: SocketException " + ((SocketException)ioe.InnerException).ErrorCode.ToString());
                        }
                    }
                    catch (Exception e) {
                        Trace.WriteLine("ConnectThread exception: " + e.ToString());
                    }
                }

                for (int i=0; ((i<10) && (!m_Disposed)); i++)
                    Thread.Sleep(100);
            }
            Trace.WriteLine("ConnectThread is ending.", this.GetType().ToString());
        }
コード例 #29
0
 /// <summary>
 /// Remove the given ParticipantModel
 /// </summary>
 /// <param name="value">The ParticipantModel to remove</param>
 public void Remove( ParticipantModel value )
 {
     List.Remove(value);
 }
コード例 #30
0
            /// <summary>
            /// Creates a <see cref="ParticipantModel"/> and <see cref="RTPMessageReceiver"/>
            /// whenever a new stream is connected to the venue.  The <see cref="ParticipantModel"/>
            /// is added to the current <see cref="ClassroomModel"/>.
            /// </summary>
            private void HandleStreamAdded(object sender, RtpEvents.RtpStreamEventArgs args)
            {
                using(Synchronizer.Lock(this.m_Sender.m_Classroom.SyncRoot)) {
                    using(Synchronizer.Lock(this)) {
                        if(this.m_Disposed) throw new ObjectDisposedException("RTPMessageSender");

                        RtpStream stream = args.RtpStream;

                        // Ignore streams that are not part of our session.
                        if(this.m_Sender.m_RtpSession.ContainsStream(stream)) {
                            // Ignore streams that are not DynamicPresentations.
                            if(stream.PayloadType == PayloadType.dynamicPresentation) {
                                // Ignore our own stream, but create a listener for all others.
                                if(stream.SSRC != this.m_Sender.m_RtpSender.SSRC) {

                                    // If we've not seen this client before, create a new ParticipantModel,
                                    // identified by the participant's CName, which, if the participant
                                    // is running Classroom Presenter, is a Guid string.
                                    string cname = stream.Properties.CName;

                                    // It's possible for a participant to generate more than one Rtp stream,
                                    // so we need to keep a different table for m_Participants than m_Receivers.
                                    ParticipantModel participant = ((ParticipantModel) this.m_Participants[cname]);
                                    if(participant == null) {
                                        // Also get the remote client's HumanName from the participant data.
                                        RtpParticipant client = this.m_Sender.m_RtpSession.Participants[cname];
                                        participant = new ParticipantModel(new Guid(cname), client.Name);
                                        // Add the participant to our table.
                                        this.m_Participants.Add(cname, participant);
                                    }

                                    // Add the participant to the classroom if it is not already a member.
                                    if(!this.m_Sender.m_Classroom.Participants.Contains(participant))
                                        this.m_Sender.m_Classroom.Participants.Add(participant);

                                    // Create a receiver for this specific stream (there may be more than one stream per participant)
                                    // and add it to the table of receivers so it can be disposed when the stream is removed.
                                    RTPMessageReceiver receiver = new RTPMessageReceiver(this.m_Sender, stream,
                                        this.m_Sender.m_Model, this.m_Sender.m_Classroom, participant);
                                    this.m_Receivers.Add(stream, receiver);
                                }
                            }
                        }
                    }
                }
            }
コード例 #31
0
 /// <summary>
 /// Returns the index of the given object
 /// </summary>
 /// <param name="value">The ParticipantModel to find the index of</param>
 /// <returns>The index of the object, or -1 otherwise</returns>
 public int IndexOf( ParticipantModel value )
 {
     return List.IndexOf(value);
 }
コード例 #32
0
 internal ReceiveContext(PresenterModel model, ClassroomModel classroom, ParticipantModel participant)
 {
     this.Model = model;
     this.Classroom = classroom;
     this.Participant = participant;
 }
コード例 #33
0
 /// <summary>
 /// Determines if the specified <see cref="ParticipantModel"/> is in the collection.
 /// </summary>
 public bool Contains(ParticipantModel value)
 {
     return(List.Contains(value));
 }
コード例 #34
0
        //Construct
        public VersionExchange(ParticipantModel participant)
        {
            m_RemoteParticipant = participant;

            //Check local role
            using (Synchronizer.Lock(PresenterModel.TheInstance.Participant.SyncRoot)) {
                if (PresenterModel.TheInstance.Participant.Role is InstructorModel) {
                    this.m_LocalNodeIsInstructor = true;
                }
            }

            //Check and subscribe for changes to remote role
            using (Synchronizer.Lock(m_RemoteParticipant.SyncRoot)) {
                m_RemoteHumanName = m_RemoteParticipant.HumanName;
                if (m_RemoteParticipant.Role is InstructorModel) {
                    m_RemoteNodeIsInstructor = true;
                }
                m_RemoteParticipant.Changed["Role"].Add(new PropertyEventHandler(RoleChangedHandler));
            }

            //Flag instructor nodes to initiate the exchange by sending the request message.
            if (m_LocalNodeIsInstructor) {
                m_SendRequest = true;
            }
        }
コード例 #35
0
        /// <summary>
        /// Set the SequenceNumber property for the specified item, then enqueue it.
        /// </summary>
        /// <param name="sp"></param>
        public void Enqueue(SendParameters sp, ParticipantModel participant)
        {
            lock (this) {
                sp.SequenceNumber = m_NextSequenceNumber;
                m_NextSequenceNumber++;

                if (m_QueueList.ContainsKey(sp.Id)) {
                    ((ClientQueue)m_QueueList[sp.Id]).Enqueue(sp);
                }
                else {
                    ClientQueue cq = new ClientQueue(sp.Id, participant);
                    cq.Enqueue(sp);
                    m_QueueList.Add(sp.Id, cq);
                }
                //Trace.WriteLine("Enqueue guid=" + sp.Tags.SlideID.ToString() + "; seq =" + sp.SequenceNumber.ToString(), this.GetType().ToString());
            }
        }
コード例 #36
0
        /// <summary>
        /// Called when a VersionRequestMessage is received
        /// </summary>
        /// <param name="remoteParticipant"></param>
        /// <param name="version"></param>
        public void ReceiveVersionRequest(ParticipantModel remoteParticipant, VersionRequestMessage requestMessage)
        {
            Trace.WriteLine("VersionExchangeModel.ReceiveVersionRequest started. remoteParticipant=" +
                remoteParticipant.Guid.ToString() + "; requesterID= " + requestMessage.RequesterId.ToString());
            VersionExchange ve;
            //Make a VersionExchange object if needed.
            using (Synchronizer.Lock(this.SyncRoot)) {
                if (m_VersionExchangeDictionary.ContainsKey(remoteParticipant.Guid)) {
                    ve = m_VersionExchangeDictionary[remoteParticipant.Guid];
                }
                else {
                    //This probably should not happen, but if it does we are covered.
                    ve = new VersionExchange(remoteParticipant);
                    m_VersionExchangeDictionary.Add(remoteParticipant.Guid, ve);
                    m_VersionExchanges.Add(ve);
                    Trace.WriteLine("Created a VersionExchange in response to Version Request from participant: " + remoteParticipant.Guid.ToString());
                }
            }

            //Let the VersionExchange object process the inbound message
            ve.ReceiveRequest(requestMessage.RequesterVersion);
        }
コード例 #37
0
            public ClientQueue(Guid id, ParticipantModel participant)
            {
                m_Participant = participant;
                m_IsPublicNode = false;
                m_Participant.Changed["Role"].Add(new PropertyEventHandler(OnRoleChanged));
                using (Synchronizer.Lock(m_Participant.SyncRoot)) {
                    if (m_Participant.Groups.Contains(Group.AllPublic)) {
                        m_IsPublicNode = true;
                    }
                }

                this.m_Id = id;
                this.m_List = new LinkedList<SendParameters>();
                this.m_SlideQueues = new Hashtable();
                this.m_ReconnectBuffer = new ReconnectBuffer();
            }
コード例 #38
0
        /// <summary>
        /// When a participant is removed from a classroom, clean up the version exchange
        /// </summary>
        /// <param name="value"></param>
        internal void RemoveVersionExchange(ParticipantModel participant)
        {
            if ((participant.Guid.Equals(Guid.Empty)) ||
                (participant.Guid.Equals(PresenterModel.ParticipantId)) ||
                (!m_VersionExchangeDictionary.ContainsKey(participant.Guid))) {
                return;
            }

            using (Synchronizer.Lock(this.SyncRoot)) {
                Trace.WriteLine("Removing VersionExchange for participant: " + participant.Guid.ToString());
                VersionExchange ve = m_VersionExchangeDictionary[participant.Guid];
                m_VersionExchanges.Remove(ve);
                m_VersionExchangeDictionary.Remove(participant.Guid);
            }
        }
コード例 #39
0
 /// <summary>
 /// After a client reconnect, we may have a new ParticipantModel, so resubscribe for Role changes.
 /// </summary>
 /// <param name="participant"></param>
 internal void UpdateParticipant(ParticipantModel participant)
 {
     this.m_Participant.Changed["Role"].Remove(new PropertyEventHandler(OnRoleChanged));
     m_Participant = participant;
     m_IsPublicNode = false;
     m_Participant.Changed["Role"].Add(new PropertyEventHandler(OnRoleChanged));
     using (Synchronizer.Lock(m_Participant.SyncRoot)) {
         if (m_Participant.Groups.Contains(Group.AllPublic)) {
             m_IsPublicNode = true;
         }
     }
 }
コード例 #40
0
        protected override void OnClick(EventArgs e)
        {
            base.OnClick(e);
            this.clicked = true;

            if (this.m_Association != null) {
                // Set the role accordingly
                using (Synchronizer.Lock(this.m_Model.Participant)) {
                    if (this.m_Model.Participant.Role is InstructorModel || this.m_Model.Participant.Role == null)
                        this.m_Model.Participant.Role = new StudentModel(Guid.NewGuid());
                    }

                // Set the network association
                using (Synchronizer.Lock(this.m_Model.Network.SyncRoot)) {
                    this.m_Model.Network.Association = this.Association;
                    }
                } else {
                // Instead Start an Empty Presentation
                StartJoinButton2.StartEmptyPresentation(this.m_Model);
                }
        }
コード例 #41
0
 /// <summary>
 /// Constructor for the PresentationModel
 /// </summary>
 /// <param name="id">The unique identifier for this presentation</param>
 /// <param name="owner">The ParticipantModel of the owner of this presentation</param>
 /// <param name="humanName">The friendly name for this presentation</param>
 public PresentationModel(Guid id, ParticipantModel owner, string humanName)
     : this(id,owner,humanName,false)
 {
 }