Пример #1
0
        /// <summary>
        /// Handles the asynchronous reception of UDP packets on the socket.
        /// </summary>
        /// <param name="ar">The <see cref="IAsyncResult" /> instance.</param>
        private void OnReceive(IAsyncResult ar)
        {
            AuthTransaction transaction;
            RadiusPacket    response;

            byte[] rawPacket;
            int    cbPacket;

            // Complete receiving the packet and then initiate reception
            // of the next packet.  Note that I don't need a lock here
            // because there's never more than one async packet receive
            // outstanding at a given time.

            try
            {
                cbPacket  = sock.EndReceiveFrom(ar, ref sourceEP);
                rawPacket = (byte[])recvBuf.Clone();
                sock.BeginReceiveFrom(recvBuf, 0, recvBuf.Length, SocketFlags.None, ref sourceEP, onReceive, null);

                response = new RadiusPacket((IPEndPoint)sourceEP, rawPacket, cbPacket);
            }
            catch (SocketClosedException)
            {
                // We'll see this when the RADIUS server instance is closed.
                // I'm not going to report this to the event log.

                return;
            }
            catch (Exception e)
            {
                SysLog.LogException(e);
                return;
            }

            // Map the packet to a transaction and signal that the
            // authentication transaction is complete.

            using (TimedLock.Lock(this))
            {
                if (!isOpen)
                {
                    return;
                }

                transaction = transactions[response.Identifier];
                if (transaction == null)
                {
                    return;     // The transaction must have been aborted
                }
                // Validate the response authenticator, discarding the packet
                // if it's not valid.

                if (!response.VerifyResponseAuthenticator(transaction.Packet, secret))
                {
                    transaction.AsyncResult.Result = false;
                }
                else
                {
                    // Complete the outstanding transaction if the packet is a
                    // valid answer.

                    switch (response.Code)
                    {
                    case RadiusCode.AccessAccept:

                        transaction.AsyncResult.Result = true;
                        break;

                    case RadiusCode.AccessReject:

                        transaction.AsyncResult.Result = false;
                        break;

                    default:

                        return;         // Ignore all other answers
                    }
                }

                transaction.AsyncResult.Notify();
                transactions[response.Identifier] = null;
            }
        }