/** * Helios, OpenSource Monitoring * Brought to you by the Helios Development Group * * Copyright 2007, Helios Development Group and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. * */ package org.helios.apmrouter.nativex; import org.helios.apmrouter.util.BitMaskedEnum; import org.helios.apmrouter.util.SimpleLogger; import java.util.Arrays; import java.util.HashSet; import java.util.Map; import java.util.Set; import static org.helios.apmrouter.util.BitMaskedEnum.Support.generateIntMaskMap; import static org.helios.apmrouter.util.BitMaskedEnum.Support.getIntBitMask; import static org.helios.apmrouter.util.Methods.nvl; /** * <p>Title: TCPSocketState</p> * <p>Description: A functional bitmasked enum representing TCP socket states</p> * <p>Company: Helios Development Group LLC</p> * @author Whitehead (nwhitehead AT heliosdev DOT org) * <p><code>org.helios.apmrouter.nativex.TCPSocketState</code></p> */ public enum TCPSocketState implements BitMaskedEnum { /** The socket state for ESTABLISHED */ TCP_ESTABLISHED(1), /** The socket state for SYN_SENT */ TCP_SYN_SENT(2), /** The socket state for SYN_RECV */ TCP_SYN_RECV(3), /** The socket state for FIN_WAIT1 */ TCP_FIN_WAIT1(4), /** The socket state for FIN_WAIT2 */ TCP_FIN_WAIT2(5), /** The socket state for TIME_WAIT */ TCP_TIME_WAIT(6), /** The socket state for CLOSE */ TCP_CLOSE(7), /** The socket state for CLOSE_WAIT */ TCP_CLOSE_WAIT(8), /** The socket state for LAST_ACK */ TCP_LAST_ACK(9), /** The socket state for LISTEN */ TCP_LISTEN(10), /** The socket state for CLOSING */ TCP_CLOSING(11), /** The socket state for IDLE */ TCP_IDLE(12), /** The socket state for BOUND */ TCP_BOUND(13), /** The socket state for UNKNOWN */ TCP_UNKNOWN(14); /** A decoding map to decode the NetFlag code to a TCPSocketState */ public static final Map<Integer, TCPSocketState> CODE2ENUM = generateIntMaskMap(TCPSocketState.values()); private TCPSocketState(int code) { this.code = code; mask = getIntBitMask(this); } /** The code for this state */ private final int code; /** The mask for this state */ private final int mask; /** * Returns the code for this state * @return the code for this state */ public int getCode() { return code; } /** * Returns the mask for this state * @return the mask for this state */ public int getMask() { return mask; } /** * Accepts the passed int state and enables the passed socket states on it * @param i The initial state code * @param states The states to enable * @return the modified state code */ public static int enable(int i, TCPSocketState...states) { int mask = i; if(states!=null) { for(TCPSocketState state: states) { if(state==null) continue; mask = mask | state.mask; } } return mask; } /** * Accepts the passed int state and disables the passed socket states on it * @param i The initial state code * @param states The states to disable * @return the modified state code */ public static int disable(int i, TCPSocketState...states) { int mask = i; if(states!=null) { for(TCPSocketState state: states) { if(state==null) continue; mask = mask & ~state.mask; } } return mask; } /** * Returns a state code that represents the mask of all the passed socket states * @param states The socket states to enable * @return the mask that represents all the socket states. */ public static int enable(TCPSocketState...states) { return enable(0, states); } /** * Determines if the passed mask is enabled for all the specified socket states * @param mask The mask to test * @param state The socket states to test for * @return true if the passed mask is enabled for all the specified socket states, false otherwise */ public static boolean enabledForAll(int mask, TCPSocketState...state) { if(state==null) throw new IllegalArgumentException("The passed state was null", new Throwable()); for(TCPSocketState t: state) { if(t==null) continue; if((mask| t.mask) != mask) return false; } return true; } /** * Determines if the passed mask is disabled for all the specified socket states * @param mask The mask to test * @param state The socket states to test for * @return true if the passed mask is disabled for all the specified socket states, false otherwise */ public static boolean disabledForAll(int mask, TCPSocketState...state) { if(state==null) throw new IllegalArgumentException("The passed state was null", new Throwable()); for(TCPSocketState t: state) { if(t==null) continue; if((mask & ~t.mask) != mask) return false; } return true; } /** * Determines if the passed mask is enabled for any the specified socket states * @param mask The mask to test * @param state The socket states to test for * @return true if the passed mask is enabled for at least one of the specified socket states, false otherwise */ public static boolean enabledForAny(int mask, TCPSocketState...state) { if(state==null) throw new IllegalArgumentException("The passed state was null", new Throwable()); for(TCPSocketState t: state) { if(t==null) continue; if((mask | t.mask) == mask) return true; } return false; } /** * Determines if the passed mask is disabled for any the specified socket states * @param mask The mask to test * @param state The socket states to test for * @return true if the passed mask is disabled for at least one of the specified socket states, false otherwise */ public static boolean disabledForAny(int mask, TCPSocketState...state) { if(state==null) throw new IllegalArgumentException("The passed state was null", new Throwable()); for(TCPSocketState t: state) { if(t==null) continue; if((mask & ~t.mask) == mask) return true; } return false; } /** * Determines if the passed mask is enabled for this socket state * @param mask the mask to test * @return true if the passed mask is enabled for this socket state, false otherwise */ public boolean isEnabled(int mask) { return (mask | this.mask) == mask; } /** * Enables the passed mask for this socket state and returns it * @param mask The mask to modify * @return the modified mask */ public int enable(int mask) { return (mask | this.mask); } /** * Disables the passed mask for this socket state and returns it * @param mask The mask to modify * @return the modified mask */ public int disable(int mask) { return (mask & ~this.mask); } /** * Returns an array of socket states that enabled in the passed mask * @param mask The masks to get the states for * @return an array of socket states that enabled in the passed mask */ public static TCPSocketState[] getEnabledStates(int mask) { Set<TCPSocketState> enabled = new HashSet<TCPSocketState>(); for(TCPSocketState t: values()) { if(t.isEnabled(mask)) enabled.add(t); } return enabled.toArray(new TCPSocketState[enabled.size()]); } /** * Returns a compound name representing all the socket states that enabled in the passed mask * @param mask The masks to get the states for * @return a compound name representing all the socket states that enabled in the passed mask */ public static String getEnabledStatesName(int mask) { return Arrays.toString(getEnabledStates(mask)).replace("[", "").replace("]", "").replace(" ", "").replace(',', '|'); } /** * Returns the masked int for the passed NetStat socket state int array * @param arr a NetStat socket state int array (an array of 14 ints) * @return a socket state mask */ public static int getMaskedArray(int[] arr) { return enable(valueOf(arr)); } public static void main(String[] args) { for(TCPSocketState t: values()) { //SimpleLogger.info(t.name(), "[", t.mask, "]:", Integer.toBinaryString(t.mask)); } int mask = enable(TCP_CLOSE_WAIT, TCP_FIN_WAIT2); SimpleLogger.info("CloseWait and FinWait2:", mask, "[", Integer.toBinaryString(mask), "]"); for(TCPSocketState t: values()) { if(t.isEnabled(mask)) SimpleLogger.info("Enabled for [", t, "]"); } SimpleLogger.info("Enabled for All CloseWait and FinWait2:", enabledForAll(mask, TCP_CLOSE_WAIT, TCP_FIN_WAIT2), " ", getEnabledStatesName(mask)); SimpleLogger.info("Enabled for All CloseWait and FinWait2 and TimeWait:", enabledForAll(mask, TCP_CLOSE_WAIT, TCP_FIN_WAIT2, TCP_TIME_WAIT), " ", getEnabledStatesName(mask)); SimpleLogger.info("Adding TimeWait"); mask = TCP_TIME_WAIT.enable(mask); SimpleLogger.info("Enabled for All CloseWait and FinWait2 and TimeWait:", enabledForAll(mask, TCP_CLOSE_WAIT, TCP_FIN_WAIT2, TCP_TIME_WAIT), " ", getEnabledStatesName(mask)); SimpleLogger.info("Disabling TimeWait"); mask = TCP_TIME_WAIT.disable(mask); SimpleLogger.info("Enabled for All CloseWait and FinWait2 and TimeWait:", enabledForAll(mask, TCP_CLOSE_WAIT, TCP_FIN_WAIT2, TCP_TIME_WAIT), " ", getEnabledStatesName(mask)); } /** * Decodes the passed name to a TCPSocketState. * Throws a runtime exception if the ordinal is invalid * @param name The socket state name type name to decode. Trimmed and uppercased. * @return the decoded TCPSocketState */ public static TCPSocketState valueOfName(CharSequence name) { String n = nvl(name, "TCPSocketState Name").toString().trim().toUpperCase(); try { return TCPSocketState.valueOf(n); } catch (Exception e) { throw new IllegalArgumentException("The passed name [" + name + "] is not a valid TCPSocketState name", new Throwable()); } } /** * Decodes the passed array of states to an array of TCPSocketStates. * Ignores any invalid indexes in the array * @param codes A netstat array of socket state codes * @return the decoded TCPSocketState array */ public static TCPSocketState[] valueOf(int...codes) { int[] c = nvl(codes, "TCPSocketState Codes"); Set<TCPSocketState> states = new HashSet<TCPSocketState>(); for(int i = 1; i < codes.length; i++) { if(c[i] > 0) try { states.add(TCPSocketState.valueOf(i)); } catch (Exception e) {} } return states.toArray(new TCPSocketState[states.size()]); } /** * Decodes the passed code to a TCPSocketState. * Throws a runtime exception if the code is invalud * @param code The code to decode * @return the decoded TCPSocketState */ public static TCPSocketState valueOf(int code) { TCPSocketState t = CODE2ENUM.get(code); if(t==null) throw new IllegalArgumentException("The passed code [" + code+ "] is not a valid TCPSocketState code", new Throwable()); return t; } }