Ejemplo n.º 1
0
        /// <summary>
        /// Receive loop continually receives data.
        /// </summary>
        private void ReceiveLoop()
        {
            int iExCount = 0;

            if (m_CurrentIP == "")
            {
                m_LocalEndPoint = new IPEndPoint(IPAddress.Any, m_CurrentPort);
            }
            else
            {
                m_LocalEndPoint = new IPEndPoint(IPAddress.Parse(m_CurrentIP), m_CurrentPort);
            }

            DebugDump("Created the local IP endpoint at " + m_LocalEndPoint.ToString( ));
            try
            {
                m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                DebugDump("Created the socket.");

                m_Socket.Bind(m_LocalEndPoint);
                DebugDump("Bound the socket to the local end point, now entering receive loop...");

                m_iState = UdpConsts.UDP_STATE_LISTENING;

                if (OnListenStateChanged != null)
                {
                    OnListenStateChanged(null, new ListenEventArgs(true));
                }

                while (true)
                {
                    try
                    {
                        //Make space to store the data from the socket
                        Byte[] received = new Byte[UdpConsts.MAX_COMMAND_LEN];

                        //Create an end point, just give it temporary values
                        EndPoint remoteEP = new IPEndPoint(m_LocalEndPoint.Address, m_LocalEndPoint.Port);

                        //Read bytes from the socket
                        int        bytesReceived = m_Socket.ReceiveFrom(received, ref remoteEP);
                        IPEndPoint remoteIPEP    = (IPEndPoint)remoteEP;

                        //string str_received = Encoding.UTF8.GetString(received);
                        string str_received = Util.BytesToString(received);
                        str_received = str_received.Substring(0, bytesReceived);

                        //Fire the received event if it is being used (allowing raw data to be caught)
                        if (OnDataReceived != null)
                        {
                            OnDataReceived(null, new ReceivedEventArgs((IPEndPoint)remoteEP, str_received));
                        }

                        //Handle connectionless packets
                        try
                        {
                            int pcmd = 0;

                            //Allocate a temporary command object
                            Command new_cmd = new Command();

                            //Parse the start of the command
                            new_cmd.OPCode      = str_received.Substring(pcmd, 2);
                            pcmd               += 2;
                            new_cmd.SequenceNum = Util.BytesToUint(str_received.Substring(pcmd, 4));
                            pcmd               += 4;
                            new_cmd.Flags       = (byte)str_received[pcmd];
                            pcmd++;

                            //If the command packet is connectionless then parse it now.
                            if ((new_cmd.Flags & UdpConsts.FLAGS_CONNECTIONLESS) > 0)
                            {
                                new_cmd.NumFields = Util.BytesToShort(str_received.Substring(pcmd, 2));
                                pcmd += 2;
                                new_cmd.FieldSizes = new short[new_cmd.NumFields];
                                for (short i = 0; i < new_cmd.NumFields; i++)
                                {
                                    new_cmd.FieldSizes[i] = Util.BytesToShort(str_received.Substring(pcmd, 2));
                                    pcmd += 2;
                                }
                                pcmd += 2;
                                new_cmd.AllFields = str_received.Substring(pcmd);
                                new_cmd.Initialize();

                                //Process the connectionless command
                                ProcessConnectionlessComand(remoteIPEP, new_cmd);
                            }
                            else
                            {
                                //Locate connection this command belongs to and process it there.
                                Connection conn;

                                //Check both the client and server lists
                                m_Clients.ConnectionByRemoteEndpoint(remoteIPEP, out conn);
                                if (conn == null)
                                {
                                    m_Servers.ConnectionByRemoteEndpoint(remoteIPEP, out conn);
                                }

                                if (conn == null)
                                {
                                    DebugDump("Connection-related packet with no matching connection arrived - ignored.");
                                }
                                else
                                {
                                    conn.ProcessCommandPacket(str_received);
                                }
                            }
                        }
                        catch
                        {
                            DebugDump("Exception whilst parsing input from " + remoteIPEP.ToString() + " as command, probably not a command. Ignoring.");
                        }

                        //Reset the exception count to 0
                        iExCount = 0;
                    }
                    catch (SocketException se)
                    {
                        if ((se.ErrorCode != 10061) && (se.ErrorCode != 10054))
                        {
                            //Fire the socket error event.
                            if (se.ErrorCode != 10004)
                            {
                                if (OnSocketError != null)
                                {
                                    OnSocketError(null, new SocketEventArgs(se.ErrorCode, se.Message));
                                }
                            }

                            DebugDump("Socket Exception in receive loop (" + se.ErrorCode.ToString() + "): " + se.Message);
                            if (m_iState != UdpConsts.UDP_STATE_LISTENING)
                            {
                                break;
                            }

                            iExCount++;
                        }
                    }
                    catch (Exception e)
                    {
                        DebugDump("Exception in receive loop: " + e.Message);
                        if (m_iState != UdpConsts.UDP_STATE_LISTENING)
                        {
                            break;
                        }

                        iExCount++;
                    }

                    if (iExCount == UdpConsts.MAX_EXCEPTIONS)
                    {
                        DebugDump("Got too many consecutive exceptions in the receive loop, terminating.");
                        break;
                    }
                }
            }
            catch (SocketException se)
            {
                //Fire the socket error event.
                if (OnSocketError != null)
                {
                    OnSocketError(null, new SocketEventArgs(se.ErrorCode, se.Message));
                }

                DebugDump("Socket Exception (" + se.ErrorCode.ToString() + "): " + se.Message);
            }
            catch (Exception e)
            {
                DebugDump("Exception: " + e.Message);
            }

            //We are out of the loop but the server thinks we are not? make sure it does.
            if ((m_iState != UdpConsts.UDP_STATE_IDLE) && (m_iState != UdpConsts.UDP_STATE_CLOSING))
            {
                StopListen();
            }

            DebugDump("Set the system state to idle.");

            //Set the state to idle.
            m_iState = UdpConsts.UDP_STATE_IDLE;

            DebugDump("Exited the receive loop.");
        }