/// <summary>
        /// Enqueue the send to occur when network bandwidth is available.
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="length"></param>
        /// <param name="socket"></param>
        /// <param name="participant"></param>
        internal void Send(byte[] buffer, int length, ClientData client, MessageTags tags,
            ulong messageSequence, ulong chunkSequence, bool isHeartbeat)
        {
            using (Synchronizer.Lock(m_SocketMap)) {
                Debug.Assert(m_SocketMap.ContainsKey(client.Id), "TCPServerSender.Send found a missing Socket Map entry.");
            }

            //Trace.WriteLine("TCPServerSender.Send seq=" + messageSequence.ToString());

            //Enqueue the message
            using (Synchronizer.Cookie cookie = Synchronizer.Lock(m_SendQueue)) {
                m_SendQueue.Enqueue(new SendParameters(buffer, length, client.Id, tags, messageSequence, chunkSequence, isHeartbeat),
                    client.Participant);

                // Notify the sender thread that the queue's status has changed.
                cookie.PulseAll();
            }
        }
 /// <summary>
 /// If a client reconnects, update the socket map and enable the client's queue
 /// </summary>
 /// <param name="id"></param>
 /// <param name="s"></param>
 internal void Reconnect(ClientData client, ulong lastMessage, ulong lastChunk)
 {
     using (Synchronizer.Lock(this.m_SocketMap)) {
         if (m_SocketMap.ContainsKey(client.Id)) {
             m_SocketMap[client.Id] = client.Socket;
         }
     }
     using (Synchronizer.Cookie cookie = Synchronizer.Lock(this.m_SendQueue)) {
         m_SendQueue.EnableClient(client, lastMessage, lastChunk);
         cookie.PulseAll();
     }
 }
 internal void AddClient(ClientData client)
 {
     using (Synchronizer.Lock(m_SocketMap)) {
         Debug.Assert(!m_SocketMap.ContainsKey(client.Id), "TCPServerSender.AddClient: Attempt to add a duplicate Socket Map entry.");
         m_SocketMap.Add(client.Id, client.Socket);
     }
 }
 /// <summary>
 /// Enable dequeue for a client's queue
 /// </summary>
 /// <param name="client"></param>
 public void EnableClient(ClientData client, ulong lastMessage, ulong lastChunk)
 {
     Trace.WriteLine("TCPServerSendQueue Enable client id=" + client.Id.ToString(), this.GetType().ToString());
     lock (this) {
         if (m_DisabledClients.ContainsKey(client.Id)) {
             m_DisabledClients.Remove(client.Id);
         }
         if (m_QueueList.ContainsKey(client.Id)) {
             ((ClientQueue)m_QueueList[client.Id]).RecoverMessages(lastMessage, lastChunk);
             ((ClientQueue)m_QueueList[client.Id]).UpdateParticipant(client.Participant);
         }
     }
 }
Example #5
0
        /// <summary>
        /// When the ListenThread has a prospective new client on the line, here we attempt to establish the connection.
        /// </summary>
        /// <param name="ar"></param>
        private void AcceptSocketCallback(IAsyncResult ar)
        {
            Socket s = null;
            TcpListener tcpListener = (TcpListener)ar.AsyncState;

            try {
                s = tcpListener.EndAcceptSocket(ar);
            }
            catch (ObjectDisposedException ode) {
                Trace.WriteLine("AcceptSocketCallback ObjectDisposedException" + ode.Message, this.GetType().ToString());
                return;
            }
            catch (SocketException se) {
                Trace.WriteLine("AcceptSocketCallback: " + se.ToString(), this.GetType().ToString());
                return;
            }
            catch (Exception e) {
                Trace.WriteLine(e.ToString(), this.GetType().ToString());
                return;
            }
            finally {
                m_ClientConnected.Set();  //Let the ListenThread continue
            }

            if (s != null) {
                try {
                    //Send a handshake
                    NetworkStream ns = new NetworkStream(s); //Here the network stream does not "own" the socket, so we have to close it explicitly.
                    BinaryFormatter bf = new BinaryFormatter();
                    MemoryStream ms = new MemoryStream();
                    TCPHandshakeMessage handshake = new TCPHandshakeMessage(this.m_Participant, new IPEndPoint(0, 0));
                    bf.Serialize(ms, handshake);
                    ns.Write(ms.GetBuffer(), 0, (int)ms.Length);
                    Trace.WriteLine("Handshake sent.", this.GetType().ToString());

                    //Receive a handshake
                    object o = bf.Deserialize(ns);

                    if (o is TCPHandshakeMessage) {
                        TCPHandshakeMessage h = (TCPHandshakeMessage)o;
                        Trace.WriteLine("Handshake received from " + h.ParticipantId.ToString() + " ep=" + h.EndPoint.ToString(), this.GetType().ToString());
                        ParticipantModel p;

                        //In case this client still has a socket open, force it to close
                        ClosePreviousSocket(h.ParticipantId);

                        //Notice that as soon as we add the entry to m_AllClients, it is eligible for sending of outbound messages:
                        bool newClient = false;
                        lock (m_AllClients) {
                            if (m_AllClients.ContainsKey(h.ParticipantId)) {
                                ((ClientData)m_AllClients[h.ParticipantId]).ConnectionState = ConnectionState.Connected;
                                ((ClientData)m_AllClients[h.ParticipantId]).Socket = s;
                                p = ((ClientData)m_AllClients[h.ParticipantId]).Participant;
                                //Add the participant to the classroom model
                                using (Synchronizer.Lock(m_Classroom.SyncRoot)) {
                                    m_Classroom.Participants.Add(p);
                                }
                                ((ClientData)m_AllClients[h.ParticipantId]).Timeout = DateTime.MaxValue;
                                this.m_ServerSender.Reconnect(((ClientData)m_AllClients[h.ParticipantId]), h.LastMessageSequence, h.LastChunkSequence);
                            }
                            else {
                                p = new ParticipantModel(h.ParticipantId,h.HumanName);
                                //Add the participant to the classroom model
                                using (Synchronizer.Lock(m_Classroom.SyncRoot)) {
                                    m_Classroom.Participants.Add(p);
                                }
                                ClientData client = new ClientData(s,h.ParticipantId,p);
                                this.m_ServerSender.AddClient(client);
                                m_AllClients.Add(h.ParticipantId, client);
                                newClient = true;
                            }
                        }

                        //Update connected client count for network status
                        using (Synchronizer.Lock(this.SyncRoot)) {
                            this.SetPublishedProperty("ClientCount", ref this.m_ClientCount, this.m_ClientCount+1);
                            NetworkStatus newStatus = m_NetworkStatus.Clone();
                            newStatus.ClientCount = this.m_ClientCount;
                            this.SetPublishedProperty("NetworkStatus", ref m_NetworkStatus, newStatus);
                        }

                        //Start a receive thread for this socket.
                        Thread receiveThread = new Thread(ReceiveThread);
                        receiveThread.Start(new ReceiveThreadArgs(p, ns, s.RemoteEndPoint));

                        //Send the current presentation state if this is a new client
                        if (newClient) {
                            m_Sender.ForceUpdate(new SingletonGroup(p));
                        }
                    }
                    else {
                        Trace.WriteLine("AcceptSocketCallback invalid handshake from " + s.RemoteEndPoint.ToString(), this.GetType().ToString());
                    }
                }
                catch (Exception e) {
                    Trace.WriteLine("AcceptSocketCallback exception while handshaking with " + s.RemoteEndPoint.ToString() + ": " + e.ToString(), this.GetType().ToString());
                }
            }
        }
Example #6
0
        /// <summary>
        /// When the ListenThread has a prospective new client on the line, here we attempt to establish the connection.
        /// </summary>
        /// <param name="ar"></param>
        private void AcceptSocketCallback(IAsyncResult ar)
        {
            Socket      s           = null;
            TcpListener tcpListener = (TcpListener)ar.AsyncState;

            try {
                s = tcpListener.EndAcceptSocket(ar);
            }
            catch (ObjectDisposedException ode) {
                Trace.WriteLine("AcceptSocketCallback ObjectDisposedException" + ode.Message, this.GetType().ToString());
                return;
            }
            catch (SocketException se) {
                Trace.WriteLine("AcceptSocketCallback: " + se.ToString(), this.GetType().ToString());
                return;
            }
            catch (Exception e) {
                Trace.WriteLine(e.ToString(), this.GetType().ToString());
                return;
            }
            finally {
                m_ClientConnected.Set();  //Let the ListenThread continue
            }

            if (s != null)
            {
                try {
                    //Send a handshake
                    NetworkStream       ns        = new NetworkStream(s); //Here the network stream does not "own" the socket, so we have to close it explicitly.
                    BinaryFormatter     bf        = new BinaryFormatter();
                    MemoryStream        ms        = new MemoryStream();
                    TCPHandshakeMessage handshake = new TCPHandshakeMessage(this.m_Participant, new IPEndPoint(0, 0));
#if GENERIC_SERIALIZATION
                    handshake.Serialize().WriteToStream(ms);
#else
                    bf.Serialize(ms, handshake);
#endif
                    ns.Write(ms.GetBuffer(), 0, (int)ms.Length);
                    Trace.WriteLine("Handshake sent.", this.GetType().ToString());

                    //Receive a handshake
#if GENERIC_SERIALIZATION
                    IGenericSerializable o = PacketTypes.DecodeMessage(null, new SerializedPacket(ns));
#else
                    object o = bf.Deserialize(ns);
#endif

                    if (o is TCPHandshakeMessage)
                    {
                        TCPHandshakeMessage h = (TCPHandshakeMessage)o;
                        Trace.WriteLine("Handshake received from " + h.ParticipantId.ToString() + " ep=" + h.EndPoint.ToString(), this.GetType().ToString());
                        ParticipantModel p;

                        //In case this client still has a socket open, force it to close
                        ClosePreviousSocket(h.ParticipantId);

                        //Notice that as soon as we add the entry to m_AllClients, it is eligible for sending of outbound messages:
                        bool newClient = false;
                        lock (m_AllClients) {
                            if (m_AllClients.ContainsKey(h.ParticipantId))
                            {
                                ((ClientData)m_AllClients[h.ParticipantId]).ConnectionState = ConnectionState.Connected;
                                ((ClientData)m_AllClients[h.ParticipantId]).Socket          = s;
                                p = ((ClientData)m_AllClients[h.ParticipantId]).Participant;
                                //Add the participant to the classroom model
                                using (Synchronizer.Lock(m_Classroom.SyncRoot)) {
                                    m_Classroom.Participants.Add(p);
                                }
                                ((ClientData)m_AllClients[h.ParticipantId]).Timeout = DateTime.MaxValue;
                                this.m_ServerSender.Reconnect(((ClientData)m_AllClients[h.ParticipantId]), h.LastMessageSequence, h.LastChunkSequence);
                            }
                            else
                            {
                                p = new ParticipantModel(h.ParticipantId, h.HumanName);
                                //Add the participant to the classroom model
                                using (Synchronizer.Lock(m_Classroom.SyncRoot)) {
                                    m_Classroom.Participants.Add(p);
                                }
                                ClientData client = new ClientData(s, h.ParticipantId, p);
                                this.m_ServerSender.AddClient(client);
                                m_AllClients.Add(h.ParticipantId, client);
                                newClient = true;
                            }
                        }

                        //Update connected client count for network status
                        using (Synchronizer.Lock(this.SyncRoot)) {
                            this.SetPublishedProperty("ClientCount", ref this.m_ClientCount, this.m_ClientCount + 1);
                            NetworkStatus newStatus = m_NetworkStatus.Clone();
                            newStatus.ClientCount = this.m_ClientCount;
                            this.SetPublishedProperty("NetworkStatus", ref m_NetworkStatus, newStatus);
                        }

                        //Start a receive thread for this socket.
                        Thread receiveThread = new Thread(ReceiveThread);
                        receiveThread.Start(new ReceiveThreadArgs(p, ns, s.RemoteEndPoint));

                        //Send the current presentation state if this is a new client
                        if (newClient)
                        {
                            m_Sender.ForceUpdate(new SingletonGroup(p));
                        }
                    }
                    else
                    {
                        Trace.WriteLine("AcceptSocketCallback invalid handshake from " + s.RemoteEndPoint.ToString(), this.GetType().ToString());
                    }
                }
                catch (Exception e) {
                    Trace.WriteLine("AcceptSocketCallback exception while handshaking with " + s.RemoteEndPoint.ToString() + ": " + e.ToString(), this.GetType().ToString());
                }
            }
        }