/* * TeleStax, Open Source Cloud Communications * Copyright 2011-2014, Telestax Inc and individual contributors * by the @authors tag. * * This program is free software: you can redistribute it and/or modify * under the terms of the GNU Affero General Public License as * published by the Free Software Foundation; either version 3 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/> * */ package org.restcomm.media.network.deprecated.channel; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; /** * Pipeline that selects a capable {@link PacketHandler} to process incoming packets. * * @author Henrique Rosa (henrique.rosa@telestax.com) * */ public class PacketHandlerPipeline { private static final Comparator<PacketHandler> REVERSE_COMPARATOR = new Comparator<PacketHandler>() { @Override public int compare(PacketHandler o1, PacketHandler o2) { return o2.compareTo(o1); } }; private final List<PacketHandler> handlers; private final AtomicInteger count; public PacketHandlerPipeline() { this.handlers = new ArrayList<PacketHandler>(5); this.count = new AtomicInteger(0); } /** * Registers a new packet handler in the pipeline.<br> * Cannot register same handler twice. * * @param handler The handler to be registered. * @return Whether the handler was successfully registered or not. */ public boolean addHandler(PacketHandler handler) { synchronized (this.handlers){ if (!handlers.contains(handler)) { handlers.add(handler); this.count.incrementAndGet(); Collections.sort(this.handlers, REVERSE_COMPARATOR); return true; } return false; } } /** * Removes an existing packet handler from the pipeline. * * @param handler The handler to be removed * @return Returns true if the handler is removed successfully. Returns false, if the handler is not registered in the * pipeline. */ public boolean removeHandler(PacketHandler handler) { synchronized (this.handlers) { boolean removed = this.handlers.remove(handler); if (removed) { this.count.decrementAndGet(); } return removed; } } /** * Gets the number of handlers registered in the pipeline. * * @return The number of registered handlers. */ public int count() { return this.count.get(); } /** * Checks whether a certain handler is already registered in the pipeline. * * @param handler The handler to look for * @return <code>true</code> if the handler is registered. Returns <code>false</code>, otherwise. */ public boolean contains(PacketHandler handler) { synchronized (this.handlers) { return this.handlers.contains(handler); } } /** * Gets the protocol handler capable of processing the packet. * * @param packet The packet to be processed * @return The protocol handler capable of processing the packet.<br> * Returns null in case no capable handler exists. */ public PacketHandler getHandler(byte[] packet) { synchronized (this.handlers) { // Search for the first handler capable of processing the packet for (PacketHandler protocolHandler : this.handlers) { if (protocolHandler.canHandle(packet)) { return protocolHandler; } } // Return null in case no handler is capable of decoding the packet return null; } } /** * Gets a <b>copy</b> of the handlers registered in the pipeline. * * @return The list of handlers registered. */ protected List<PacketHandler> getHandlers() { return this.handlers; } }