Example #1
0
        /// <summary>
        /// Handle a message received from a KCD.
        /// </summary>
        private void ProcessIncomingKcdMessage(KcdThreadHost k, AnpMsg msg)
        {
            if (k.ConnStatus == KcdThreadConnStatus.RoleReply)
            {
                if (msg.Type == KAnp.KANP_RES_FAIL_MUST_UPGRADE)
                {
                    throw new EAnpExUpgradeKwm();
                }

                else if (msg.Type != KAnp.KANP_RES_OK)
                {
                    throw new Exception(msg.Elements[1].String);
                }

                else if (msg.Minor < KAnp.LastCompMinor)
                {
                    throw new Exception("The KCD at " + k.KcdID.Host +
                                        " is too old and needs to be upgraded.");
                }

                else
                {
                    HandleConnectedKcd(k, Math.Min(msg.Minor, KAnp.Minor));
                }
            }

            else
            {
                m_toWmAnpMsgList.Add(new KcdAnpMsg(msg, k.KcdID));
            }
        }
Example #2
0
        /// <summary>
        /// Process a control message received from the WM.
        /// </summary>
        private void ProcessWmControlMsg(KcdControlMsg msg)
        {
            Debug.Assert(msg is KcdConnectionRequest);
            KcdConnectionRequest req = (KcdConnectionRequest)msg;

            // Handle new KCD to connect.
            if (req.ConnectFlag)
            {
                Debug.Assert(!m_kcdTree.ContainsKey(req.KcdID));
                m_kcdTree[req.KcdID] = new KcdThreadHost(req.KcdID);
            }

            // Disconnect the KCD, if we didn't disconnect it yet.
            else
            {
                if (!m_kcdTree.ContainsKey(req.KcdID))
                {
                    return;
                }
                KcdThreadHost kcd = m_kcdTree[req.KcdID];
                if (kcd.ConnStatus == KcdThreadConnStatus.Disconnected)
                {
                    return;
                }
                HandleDisconnectedKcd(kcd, null);
            }
        }
Example #3
0
        /// <summary>
        /// Analyse the result of the select() call for the specified KCD.
        /// </summary>
        private void UpdateStateAfterSelect(KcdThreadHost k, SelectSockets selectSockets)
        {
            try
            {
                k.CheckNoMessageReceivedInvariant();

                // We have nothing to do if we don't have an established TCP
                // connection.
                if (k.ConnStatus != KcdThreadConnStatus.Connected &&
                    k.ConnStatus != KcdThreadConnStatus.RoleReply)
                {
                    return;
                }

                // Perform transfers only if the socket is ready.
                Debug.Assert(k.Tunnel.Sock != null);
                if (!selectSockets.InReadOrWrite(k.Tunnel.Sock))
                {
                    return;
                }

                // Do up to 20 transfers (the limit exists for quenching purposes).
                for (int i = 0; i < 20; i++)
                {
                    // Send a message if possible.
                    k.SendNextQueuedMsgIfNeeded();

                    // Remember if we are sending a message.
                    bool sendingFlag = k.Tunnel.IsSendingMessage();

                    // Do transfers.
                    k.Tunnel.DoXfer();

                    // Stop if no message has been received and no message has been sent.
                    if (!k.Tunnel.HasReceivedMessage() &&
                        (!sendingFlag || k.Tunnel.IsSendingMessage()))
                    {
                        break;
                    }

                    // Process the message received.
                    if (k.Tunnel.HasReceivedMessage())
                    {
                        ProcessIncomingKcdMessage(k, k.Tunnel.GetMsg());
                    }
                }

                k.CheckNoMessageReceivedInvariant();
            }

            catch (Exception ex)
            {
                HandleDisconnectedKcd(k, ex);
            }
        }
Example #4
0
 /// <summary>
 /// Mark the KCD as disconnected, add a control message for the KCD in
 /// the control message list and add the KCD to the disconnected list.
 /// </summary>
 private void HandleDisconnectedKcd(KcdThreadHost k, Exception ex)
 {
     if (ex != null)
     {
         KLogging.Log(2, "KCD " + k.KcdID.Host + " exception: " + ex.Message);
     }
     if (k.Tunnel != null)
     {
         k.Tunnel.Disconnect();
     }
     k.ConnStatus = KcdThreadConnStatus.Disconnected;
     k.Ex         = new EAnpExKcdConn();
     m_toWmControlMsgList.Add(new KcdDisconnectionNotice(k.KcdID, k.Ex));
     m_disconnectedList.Add(k);
 }
Example #5
0
        /// <summary>
        /// Process an ANP message received from the WM.
        /// </summary>
        private void ProcessWmAnpMsg(KcdAnpMsg msg)
        {
            // Ignore messages not destined to connected KCDs.
            if (!m_kcdTree.ContainsKey(msg.KcdID))
            {
                return;
            }
            KcdThreadHost kcd = m_kcdTree[msg.KcdID];

            if (kcd.ConnStatus != KcdThreadConnStatus.Connected)
            {
                return;
            }

            // Enqueue the message.
            kcd.SendQueue.Enqueue(msg.Msg);
        }
Example #6
0
        /// <summary>
        /// Add the socket of the KCD in the select sets as needed and manage
        /// ktlstunnel.exe processes.
        /// </summary>
        private void PrepareStateForSelect(KcdThreadHost k, SelectSockets selectSockets, bool quenchFlag,
                                           ref bool connWatchFlag)
        {
            // Note: the KCD should never have received a message when this function
            // is called. The function UpdateStateAfterSelect() is responsible for
            // doing all the transfers and handling any message received after these
            // transfers.
            try
            {
                k.CheckNoMessageReceivedInvariant();

                if (k.ConnStatus == KcdThreadConnStatus.Scheduled)
                {
                    // Start ktlstunnel.exe.
                    k.ConnStatus = KcdThreadConnStatus.Connecting;
                    k.Tunnel.BeginConnect();
                }

                if (k.ConnStatus == KcdThreadConnStatus.Connecting)
                {
                    // The TCP connection is now open.
                    if (k.Tunnel.CheckConnect())
                    {
                        // Send the select role command.
                        k.SendSelectRoleMsg();

                        // Wait for the reply to arrive.
                        k.ConnStatus = KcdThreadConnStatus.RoleReply;
                    }

                    // Wait for the TCP connection to be established. We busy wait
                    // to monitor the status of ktlstunnel.exe regularly, to detect
                    // the case where the connection fails.
                    else
                    {
                        connWatchFlag = true;
                    }
                }

                if (k.ConnStatus == KcdThreadConnStatus.RoleReply)
                {
                    // Wait for the reply to arrive.
                    if (!quenchFlag)
                    {
                        k.Tunnel.UpdateSelect(selectSockets);
                    }
                }

                if (k.ConnStatus == KcdThreadConnStatus.Connected)
                {
                    // Send the next message, if possible.
                    k.SendNextQueuedMsgIfNeeded();
                    if (!quenchFlag)
                    {
                        k.Tunnel.UpdateSelect(selectSockets);
                    }
                }

                k.CheckNoMessageReceivedInvariant();
            }

            catch (Exception ex)
            {
                HandleDisconnectedKcd(k, ex);
            }
        }
Example #7
0
 /// <summary>
 /// Mark the KCD as connected and add a control message for the KCD in
 /// the control message list.
 /// </summary>
 private void HandleConnectedKcd(KcdThreadHost k, UInt32 minor)
 {
     k.ConnStatus = KcdThreadConnStatus.Connected;
     m_toWmControlMsgList.Add(new KcdConnectionNotice(k.KcdID, minor));
 }
Example #8
0
        /// <summary>
        /// Analyse the result of the select() call for the specified KCD.
        /// </summary>
        private void UpdateStateAfterSelect(KcdThreadHost k, SelectSockets selectSockets)
        {
            try
            {
                k.CheckNoMessageReceivedInvariant();

                // We have nothing to do if we don't have an established TCP
                // connection.
                if (k.ConnStatus != KcdThreadConnStatus.Connected &&
                    k.ConnStatus != KcdThreadConnStatus.RoleReply) return;

                // Perform transfers only if the socket is ready.
                Debug.Assert(k.Tunnel.Sock != null);
                if (!selectSockets.InReadOrWrite(k.Tunnel.Sock)) return;

                // Do up to 20 transfers (the limit exists for quenching purposes).
                for (int i = 0; i < 20; i++)
                {
                    // Send a message if possible.
                    k.SendNextQueuedMsgIfNeeded();

                    // Remember if we are sending a message.
                    bool sendingFlag = k.Tunnel.IsSendingMessage();

                    // Do transfers.
                    k.Tunnel.DoXfer();

                    // Stop if no message has been received and no message has been sent.
                    if (!k.Tunnel.HasReceivedMessage() &&
                        (!sendingFlag || k.Tunnel.IsSendingMessage())) break;

                    // Process the message received.
                    if (k.Tunnel.HasReceivedMessage()) ProcessIncomingKcdMessage(k, k.Tunnel.GetMsg());
                }

                k.CheckNoMessageReceivedInvariant();
            }

            catch (Exception ex)
            {
                HandleDisconnectedKcd(k, ex);
            }
        }
Example #9
0
        /// <summary>
        /// Handle a message received from a KCD.
        /// </summary>
        private void ProcessIncomingKcdMessage(KcdThreadHost k, AnpMsg msg)
        {
            if (k.ConnStatus == KcdThreadConnStatus.RoleReply)
            {
                if (msg.Type == KAnp.KANP_RES_FAIL_MUST_UPGRADE)
                    throw new EAnpExUpgradeKwm();

                else if (msg.Type != KAnp.KANP_RES_OK)
                    throw new Exception(msg.Elements[1].String);

                else if (msg.Minor < KAnp.LastCompMinor)
                    throw new Exception("The KCD at " + k.KcdID.Host +
                                        " is too old and needs to be upgraded.");

                else HandleConnectedKcd(k, Math.Min(msg.Minor, KAnp.Minor));
            }

            else m_toWmAnpMsgList.Add(new KcdAnpMsg(msg, k.KcdID));
        }
Example #10
0
        /// <summary>
        /// Add the socket of the KCD in the select sets as needed and manage
        /// ktlstunnel.exe processes.
        /// </summary>
        private void PrepareStateForSelect(KcdThreadHost k, SelectSockets selectSockets, bool quenchFlag,
            ref bool connWatchFlag)
        {
            // Note: the KCD should never have received a message when this function
            // is called. The function UpdateStateAfterSelect() is responsible for
            // doing all the transfers and handling any message received after these
            // transfers.
            try
            {
                k.CheckNoMessageReceivedInvariant();

                if (k.ConnStatus == KcdThreadConnStatus.Scheduled)
                {
                    // Start ktlstunnel.exe.
                    k.ConnStatus = KcdThreadConnStatus.Connecting;
                    k.Tunnel.BeginConnect();
                }

                if (k.ConnStatus == KcdThreadConnStatus.Connecting)
                {
                    // The TCP connection is now open.
                    if (k.Tunnel.CheckConnect())
                    {
                        // Send the select role command.
                        k.SendSelectRoleMsg();

                        // Wait for the reply to arrive.
                        k.ConnStatus = KcdThreadConnStatus.RoleReply;
                    }

                    // Wait for the TCP connection to be established. We busy wait
                    // to monitor the status of ktlstunnel.exe regularly, to detect
                    // the case where the connection fails.
                    else connWatchFlag = true;
                }

                if (k.ConnStatus == KcdThreadConnStatus.RoleReply)
                {
                    // Wait for the reply to arrive.
                    if (!quenchFlag) k.Tunnel.UpdateSelect(selectSockets);
                }

                if (k.ConnStatus == KcdThreadConnStatus.Connected)
                {
                    // Send the next message, if possible.
                    k.SendNextQueuedMsgIfNeeded();
                    if (!quenchFlag) k.Tunnel.UpdateSelect(selectSockets);
                }

                k.CheckNoMessageReceivedInvariant();
            }

            catch (Exception ex)
            {
                HandleDisconnectedKcd(k, ex);
            }
        }
Example #11
0
 /// <summary>
 /// Mark the KCD as disconnected, add a control message for the KCD in 
 /// the control message list and add the KCD to the disconnected list.
 /// </summary>
 private void HandleDisconnectedKcd(KcdThreadHost k, Exception ex)
 {
     if (ex != null) KLogging.Log(2, "KCD " + k.KcdID.Host + " exception: " + ex.Message);
     if (k.Tunnel != null) k.Tunnel.Disconnect();
     k.ConnStatus = KcdThreadConnStatus.Disconnected;
     k.Ex = new EAnpExKcdConn();
     m_toWmControlMsgList.Add(new KcdDisconnectionNotice(k.KcdID, k.Ex));
     m_disconnectedList.Add(k);
 }
Example #12
0
 /// <summary>
 /// Mark the KCD as connected and add a control message for the KCD in
 /// the control message list.
 /// </summary>
 private void HandleConnectedKcd(KcdThreadHost k, UInt32 minor)
 {
     k.ConnStatus = KcdThreadConnStatus.Connected;
     m_toWmControlMsgList.Add(new KcdConnectionNotice(k.KcdID, minor));
 }