<commit_before>/*
 * TurnServer, the OpenSource Java Solution for TURN protocol. Maintained by the
 * Jitsi community (http://jitsi.org).
 * 
 * Distributable under LGPL license. See terms of license at gnu.org.
 */

package org.jitsi.turnserver.listeners;

import java.util.logging.*;

import org.ice4j.*;
import org.ice4j.attribute.*;
import org.ice4j.message.*;
import org.ice4j.stack.*;
import org.jitsi.turnserver.stack.*;

/**
 * The class that would be handling and responding to incoming Allocation
 * requests that are Allocation and sends a success or error response
 * 
 * @author <NAME>
 */
public class AllocationRequestListener
    implements RequestListener
{
    /**
     * The <tt>Logger</tt> used by the <tt>AllocationRequestListener</tt> class
     * and its instances for logging output.
     */
    private static final Logger logger = Logger
        .getLogger(AllocationRequestListener.class.getName());

    private final TurnStack turnStack;

    /**
     * The indicator which determines whether this
     * <tt>AllocationrequestListener</tt> is currently started.
     */
    private boolean started = false;

    /**
     * Creates a new AllocationRequestListener
     * 
     * @param turnStack
     */
    public AllocationRequestListener(StunStack stunStack)
    {
        if (stunStack instanceof TurnStack)
        {
            this.turnStack = (TurnStack) stunStack;
        }
        else
        {
            throw new IllegalArgumentException("This is not a TurnStack!");
        }
    }

    @Override
    public void processRequest(StunMessageEvent evt)
        throws IllegalArgumentException
    {
        if (logger.isLoggable(Level.FINER))
        {
            logger.finer("Received request " + evt);
        }
        Message message = evt.getMessage();
        if (message.getMessageType() == Message.ALLOCATE_REQUEST)
        {
            logger.setLevel(Level.FINEST);
            logger.finest("Received a Allocation Request");
            System.out.println("Received a Allocation Request");
            
            Response response = null;
            RequestedTransportAttribute requestedTransportAttribute =
                (RequestedTransportAttribute) message
                    .getAttribute(Attribute.REQUESTED_TRANSPORT);

            DontFragmentAttribute dontFragmentAttribute =
                (DontFragmentAttribute) message
                    .getAttribute(Attribute.DONT_FRAGMENT);

            ReservationTokenAttribute reservationTokenAttribute =
                (ReservationTokenAttribute) message
                    .getAttribute(Attribute.RESERVATION_TOKEN);

            LifetimeAttribute lifetimeAttribute = 
                (LifetimeAttribute) message.getAttribute(Attribute.LIFETIME);
            
            if (lifetimeAttribute == null)
            {
                lifetimeAttribute =
                    AttributeFactory
                        .createLifetimeAttribute(
                            (int) (Allocation.MAX_LIFETIME / 1000));
            }
            
            EvenPortAttribute evenPortAttribute =
                (EvenPortAttribute) message.getAttribute(Attribute.EVEN_PORT);
            
            TransportAddress clientAddress = evt.getRemoteAddress();
            TransportAddress serverAddress = evt.getLocalAddress();
            Transport transport = Transport.UDP;
            FiveTuple fiveTuple =
                new FiveTuple(clientAddress, serverAddress, transport);
              
            Character errorCode = null;
            if (requestedTransportAttribute == null)
            {
                errorCode = ErrorCodeAttribute.BAD_REQUEST;
            }
            else if (requestedTransportAttribute.getRequestedTransport() != 17)
            {
               System.out.println(requestedTransportAttribute.getRequestedTransport());
                errorCode = ErrorCodeAttribute.UNSUPPORTED_TRANSPORT_PROTOCOL;
            }
            else if (reservationTokenAttribute != null
                && evenPortAttribute != null)
            {
                errorCode = ErrorCodeAttribute.BAD_REQUEST;
            }
            
            if (turnStack.getServerAllocation(fiveTuple)!=null)
            {
                errorCode = ErrorCodeAttribute.ALLOCATION_MISMATCH;
            }
            // do other checks here
            
            if (errorCode == null)
            {
                // do the allocation with 5-tuple
                TransportAddress relayAddress = Allocation.getNewRelayAddress();
                logger.finest("Added a new Relay Address "+relayAddress);
                System.out.println("Added a new Relay Address "+relayAddress);
                
                Allocation allocation =
                    new Allocation(relayAddress, fiveTuple,
                        lifetimeAttribute.getLifetime());
                this.turnStack.addNewServerAllocation(allocation);
                logger.finest("Added a new Allocation");
                System.out.println("Added a new Allocation");
                
                response = MessageFactory.createAllocationResponse(
                     (Request) message,
                     allocation.getFiveTuple().getClientTransportAddress(), 
                     allocation.getRelayAddress(), 
                     (int) allocation.getLifetime());
            }
            else
            {
                
                logger.finest("Error Code " + errorCode
                    + " on Allocation Request");
                System.out.println("Error Code " + (int) errorCode
                    + " on Allocation Request");
                response =
                    MessageFactory.createAllocationErrorResponse(errorCode);
            }
            
            try
            {
                turnStack.sendResponse(
                    evt.getTransactionID().getBytes(), response,
                    evt.getLocalAddress(), evt.getRemoteAddress());
            }
            catch (Exception e)
            {
                logger.log(
                    Level.INFO, "Failed to send " + response + " through "
                        + evt.getLocalAddress(), e);
                // try to trigger a 500 response although if this one failed,
                throw new RuntimeException("Failed to send a response", e);
            }
        }
        else
        {
            return;
        }
    }

    /**<commit_msg>Adds Allocation Success Response Attributes.<commit_after>/*
 * TurnServer, the OpenSource Java Solution for TURN protocol. Maintained by the
 * Jitsi community (http://jitsi.org).
 * 
 * Distributable under LGPL license. See terms of license at gnu.org.
 */

package org.jitsi.turnserver.listeners;

import java.util.logging.*;

import org.ice4j.*;
import org.ice4j.attribute.*;
import org.ice4j.message.*;
import org.ice4j.stack.*;
import org.jitsi.turnserver.stack.*;

/**
 * The class that would be handling and responding to incoming Allocation
 * requests that are Allocation and sends a success or error response
 * 
 * @author <NAME>
 */
public class AllocationRequestListener
    implements RequestListener
{
    /**
     * The <tt>Logger</tt> used by the <tt>AllocationRequestListener</tt> class
     * and its instances for logging output.
     */
    private static final Logger logger = Logger
        .getLogger(AllocationRequestListener.class.getName());

    private final TurnStack turnStack;

    /**
     * The indicator which determines whether this
     * <tt>AllocationrequestListener</tt> is currently started.
     */
    private boolean started = false;

    /**
     * Creates a new AllocationRequestListener
     * 
     * @param turnStack
     */
    public AllocationRequestListener(StunStack stunStack)
    {
        if (stunStack instanceof TurnStack)
        {
            this.turnStack = (TurnStack) stunStack;
        }
        else
        {
            throw new IllegalArgumentException("This is not a TurnStack!");
        }
    }

    @Override
    public void processRequest(StunMessageEvent evt)
        throws IllegalArgumentException
    {
        if (logger.isLoggable(Level.FINER))
        {
            logger.setLevel(Level.FINEST);
        }
        Message message = evt.getMessage();
        if (message.getMessageType() == Message.ALLOCATE_REQUEST)
        {
            logger.finest("Received a Allocation Request");
            
            Response response = null;
            RequestedTransportAttribute requestedTransportAttribute =
                (RequestedTransportAttribute) message
                    .getAttribute(Attribute.REQUESTED_TRANSPORT);

            DontFragmentAttribute dontFragmentAttribute =
                (DontFragmentAttribute) message
                    .getAttribute(Attribute.DONT_FRAGMENT);

            ReservationTokenAttribute reservationTokenAttribute =
                (ReservationTokenAttribute) message
                    .getAttribute(Attribute.RESERVATION_TOKEN);

            LifetimeAttribute lifetimeAttribute = 
                (LifetimeAttribute) message.getAttribute(Attribute.LIFETIME);
            
            EvenPortAttribute evenPort = 
                (EvenPortAttribute) message.getAttribute(Attribute.EVEN_PORT);
            
            if (lifetimeAttribute == null)
            {
                lifetimeAttribute =
                    AttributeFactory
                        .createLifetimeAttribute(
                            (int) (Allocation.MAX_LIFETIME / 1000));
            }
            
            EvenPortAttribute evenPortAttribute =
                (EvenPortAttribute) message.getAttribute(Attribute.EVEN_PORT);
            
            TransportAddress clientAddress = evt.getRemoteAddress();
            TransportAddress serverAddress = evt.getLocalAddress();
            Transport transport = Transport.UDP;
            FiveTuple fiveTuple =
                new FiveTuple(clientAddress, serverAddress, transport);
              
            Character errorCode = null;
            if(!this.turnStack.canHaveMoreAllocations())
            {
                errorCode = ErrorCodeAttribute.ALLOCATION_QUOTA_REACHED;
            }
            else if (requestedTransportAttribute == null)
            {
                errorCode = ErrorCodeAttribute.BAD_REQUEST;
            }
            else if (requestedTransportAttribute.getRequestedTransport() != 17)
            {
                errorCode = ErrorCodeAttribute.UNSUPPORTED_TRANSPORT_PROTOCOL;
            }
            else if (reservationTokenAttribute != null
                && evenPortAttribute != null)
            {
                errorCode = ErrorCodeAttribute.BAD_REQUEST;
            }
            
            if (turnStack.getServerAllocation(fiveTuple)!=null)
            {
                errorCode = ErrorCodeAttribute.ALLOCATION_MISMATCH; 
            }
            // do other checks here
            
            if (errorCode == null)
            {
                if(evenPortAttribute==null)
                {
                    evenPortAttribute =
                        AttributeFactory.createEvenPortAttribute(false);
                }
                TransportAddress relayAddress =
                    turnStack.getNewRelayAddress(evenPortAttribute.isRFlag());
                logger.finest("Added a new Relay Address "+relayAddress);
                
                Allocation allocation =
                    new Allocation(relayAddress, fiveTuple,
                        lifetimeAttribute.getLifetime());
                this.turnStack.addNewServerAllocation(allocation);
                logger.finest("Added a new Allocation");
                
                response = MessageFactory.createAllocationResponse(
                     (Request) message,
                     allocation.getFiveTuple().getClientTransportAddress(), 
                     allocation.getRelayAddress(), 
                     (int) allocation.getLifetime());
                
                XorRelayedAddressAttribute relayedXorAddress 
                    = AttributeFactory.createXorRelayedAddressAttribute(
                            allocation.getRelayAddress(),
                            evt.getTransactionID().getBytes());
                response.putAttribute(relayedXorAddress);
                
                LifetimeAttribute lifetime 
                    = AttributeFactory.createLifetimeAttribute(
                        (int)(allocation.getLifetime()));
                response.putAttribute(lifetime);
                
                XorMappedAddressAttribute clientXorAddress 
                    = AttributeFactory.createXorMappedAddressAttribute(
                        clientAddress,
                        evt.getTransactionID().getBytes());
               response.putAttribute(clientXorAddress);
                
                if(evenPort!=null)
                {
                    // TODO : logic for process and creating Reservation Token.
                    byte[] token = {7,7,7,7};
                    ReservationTokenAttribute reservationToken
                        = AttributeFactory.createReservationTokenAttribute(
                            token);
                    response.putAttribute(reservationToken);
                    if(evenPort.isRFlag())
                    {
                        TransportAddress relayAddess
                            = allocation.getRelayAddress();
                        TransportAddress nextAddress 
                            = new TransportAddress(
                                relayAddress.getAddress(),
                                relayAddress.getPort()+1,
                                relayAddress.getTransport());
                        boolean isReserved
                            = this.turnStack.reservePort(nextAddress);
                        if(isReserved)
                        {
                            logger.log(
                                Level.FINEST,
                                nextAddress+" reserved by "+fiveTuple);
                        }
                        else
                        {
                            logger.log(
                                Level.FINEST,
                                nextAddress+" not reserved by "+fiveTuple);
                        }
                    }
                }               
            }
            else
            {
                
                logger.finest("Error Code " + errorCode
                    + " on Allocation Request");
                response =
                    MessageFactory.createAllocationErrorResponse(errorCode);
            }
            
            try
            {
                turnStack.sendResponse(
                    evt.getTransactionID().getBytes(), response,
                    evt.getLocalAddress(), evt.getRemoteAddress());
            }
            catch (Exception e)
            {
                logger.log(
                    Level.INFO, "Failed to send " + response + " through "
                        + evt.getLocalAddress(), e);
                // try to trigger a 500 response although if this one failed,
                throw new RuntimeException("Failed to send a response", e);
            }
        }
        else
        {
            return;
        }
    }

    /**
{'fraction_non_alphanumeric': 0.07262932433309535, 'fraction_numerical': 0.002076977997014344, 'mean_word_length': 1.480360592401803, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '374852', 'n_tokens_mistral': 3501, 'n_tokens_neox': 3361, 'n_words': 726}