Esempio n. 1
0
        private void stopChannelButton_Click(object sender, RoutedEventArgs e)
        {
            if (mChannelA != null && mChannelB != null)
            {
                mChannelA.StopEndPoint();
                mChannelB.StopEndPoint();

                UpdateChannelStatusGUI(null, 0);

                //elimino le due code
                ConcurrentQueue <QueuePacket> qA = mChannelA.InputQueue;
                ConcurrentQueue <QueuePacket> qB = mChannelA.OutputQueue;

                QueuePacket obj = null;
                while (!qA.IsEmpty)
                {
                    qA.TryDequeue(out obj); if (obj != null)
                    {
                        obj.Dispose();
                    }
                }
                while (!qB.IsEmpty)
                {
                    qB.TryDequeue(out obj); if (obj != null)
                    {
                        obj.Dispose();
                    }
                }

                mChannelA.Dispose();
                mChannelB.Dispose();

                mChannelA = null;
                mChannelB = null;
            }
        }
        /// <summary>
        /// routine del thread di rx
        /// </summary>
        protected static void ChannelTask(object param)
        {
            EndPointTranceiver thiz = param as EndPointTranceiver;
            int  seq_num            = 0;
            bool quit_loop          = false;
            bool back_accept        = false;

            thiz.mChannelStatus = ChannelStatusEnum.Idle;

            if (!thiz.mConfigured)
            {
                return;
            }

            //1. apro la socket in listening, 1 solo slot in backlog
            Socket listSock   = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            Socket clientSock = null;

            IPEndPoint endp = new IPEndPoint(thiz.mListeningAddress, thiz.mListeningPort);

            //1a. bind
            //1b. listen
            try
            {
                listSock.Bind(endp);
                listSock.Listen(1);
                thiz.mChannelStatus = ChannelStatusEnum.Listening;

                if (thiz.mEventReceiver != null)
                {
                    Application.Current.Dispatcher.Invoke(new Action(() =>
                    {
                        thiz.mEventReceiver.OnChannelReady(thiz);
                    }));
                }
            }
            catch
            {
                if (thiz.mEventReceiver != null)
                {
                    Application.Current.Dispatcher.Invoke(new Action(() =>
                    {
                        thiz.mEventReceiver.OnGenericError(thiz, -2);
                    }));
                }
                return;
            }

            //loop thread
            while (true)
            {
                try
                {
                    //loop ACCEPT
                    while (true)
                    {
                        if (listSock.Poll(10000, SelectMode.SelectRead))
                        {
                            clientSock = listSock.Accept();
                            break;
                        }
                        else
                        {
                            if (thiz.mTranceiverShouldQuit)
                            {
                                quit_loop = true;

                                break;
                            }
                        }
                    }

                    if (quit_loop)
                    {
                        thiz.mChannelStatus = ChannelStatusEnum.Idle;

                        listSock.Close();

                        if (clientSock != null)
                        {
                            clientSock.Shutdown(SocketShutdown.Both);
                            clientSock.Close();
                        }

                        return;
                    }

                    //configuro la socket di ricezione
                    //il canale è attivo
                    thiz.mChannelStatus = ChannelStatusEnum.Active;

                    //notifico la connessione al controller
                    if (thiz.mEventReceiver != null)
                    {
                        IPEndPoint remote_endp = clientSock.RemoteEndPoint as IPEndPoint;

                        Application.Current.Dispatcher.Invoke(new Action(() =>
                        {
                            thiz.mEventReceiver.OnRemoteConnection(thiz, remote_endp.Address, remote_endp.Port);
                        }));
                    }
                }
                catch
                {
                    //uscita ACCEPT
                    listSock.Close();
                    listSock = null;

                    try
                    {
                        if (clientSock != null)
                        {
                            clientSock.Shutdown(SocketShutdown.Both);
                            clientSock.Close();
                        }
                    }
                    catch
                    {
                    }

                    thiz.mChannelStatus = ChannelStatusEnum.Idle;

                    /*if (thiz.mEventReceiver != null)
                     * {
                     *  Application.Current.Dispatcher.Invoke(new Action(() =>
                     *  {
                     *      thiz.mEventReceiver.OnGenericError(thiz, -1);
                     *  }));
                     * }*/

                    return;
                }

                //LOOP RX/TX
                try
                {
                    while (true)
                    {
                        //attesa RX per 50ms
                        if (clientSock.Poll(50000, SelectMode.SelectRead))
                        {
                            //ci sono dati da ricevere?
                            int recv_amout = clientSock.Available;

                            if (recv_amout > 0)
                            {
                                QueuePacket pkt = new QueuePacket();
                                pkt.SequenceNumber = seq_num++;
                                pkt.PayloadData    = new byte[recv_amout];

                                int recv = clientSock.Receive(pkt.PayloadData);

                                //la coda è thread safe!
                                thiz.mOutputQueue.Enqueue(pkt);
                            }
                            else
                            {
                                //socket chiusa,torno in accept
                                back_accept = true;
                                break;
                            }
                        }
                        else
                        {
                            //niente da ricevere entro il timeout
                            //trasmetto finche la coda e' piena

                            do
                            {
                                if (thiz.mTranceiverShouldQuit)
                                {
                                    quit_loop = true;
                                    break;
                                }

                                QueuePacket tx_pkt = null;

                                if (thiz.mInputQueue.TryDequeue(out tx_pkt))
                                {
                                    if (tx_pkt != null && tx_pkt.PayloadData != null && tx_pkt.PayloadData.Length > 0)
                                    {
                                        clientSock.Send(tx_pkt.PayloadData);
                                        tx_pkt.Dispose();
                                        tx_pkt = null;
                                    }
                                }
                            }while (!thiz.mInputQueue.IsEmpty);

                            if (quit_loop)
                            {
                                break;
                            }
                        }
                    }

                    //c'è stata una disconnessione oppure una richiesta di chiusura dal controller

                    //controllo uscita del controller
                    if (quit_loop)
                    {
                        thiz.mChannelStatus = ChannelStatusEnum.Idle;
                        listSock.Close();

                        try
                        {
                            clientSock.Shutdown(SocketShutdown.Both);
                            clientSock.Close();
                        }
                        catch
                        {
                            //non importa niente qui
                        }

                        //se e' una disconnessione devo chiudere
                        return;
                    }

                    //chiusura connessione del canale
                    if (back_accept)
                    {
                        thiz.mChannelStatus = ChannelStatusEnum.Listening;

                        try
                        {
                            clientSock.Shutdown(SocketShutdown.Both);
                            clientSock.Close();
                        }
                        catch
                        {
                            //non importa niente qui
                        }

                        if (thiz.mEventReceiver != null)
                        {
                            Application.Current.Dispatcher.Invoke(new Action(() =>
                            {
                                thiz.mEventReceiver.OnRemoteDisconnetion(thiz);
                            }));
                        }
                    }
                }
                catch
                {
                    //gestione errore
                    return;
                }
            }
        }