/* * This file is part of jNAT-PMPlib. * * jNAT-PMPlib 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 3 of the License, or * (at your option) any later version. * * jNAT-PMPlib 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 jNAT-PMPlib. If not, see <http://www.gnu.org/licenses/>. */ package net.tomp2p.natpmp; /** * This class manages an External Address message. This class is thread-safe. * After instantiation, this class may be added to the message queue on the * {@link NatPmpDevice}. It is important to remove the mapping before shutdown * of the {@link NatPmpDevice}. Refer to the parameters of * {@link #MapRequestMessage(boolean, int, int, long, com.hoodcomputing.natpmp.MessageResponseInterface) } * for details of how to perform this. * * @author flszen */ public class MapRequestMessage extends Message { private int internalPort; private int requestedExternalPort; private Integer externalPort; private int requestedPortMappingLifetime; private Integer portMappingLifetime; /** * Constructs a new {@link MapRequestMessage}. If * requestedPortMappingLifetime is zero, an existing port mapping is * removed. If both internalPort and requestedPortMappingLifetime are zero, * then all mappings for this host are removed. * * @param isTCP * A value of true indicates that this is a TCP mapping. A value * of false indicates that this is a UDP mapping. * @param internalPort * The port on which this client is listening. A value of zero, * along with a lifetime of zero indicates that all port mappings * for this client are to be removed. * @param requestedExternalPort * The external port to request. This port may not be available. * Always check the result of the Message to determine which * external port is assigned. A value of zero indicates that the * NAT-PMP Gateway should choose a port on its own. * @param requestedPortMappingLifetime * The time, in seconds, to request the mapping for. A value of * zero requests that this mapping is removed. Always check the * result of the Message to determine the actual lifetime that * was assigned, as it may be different than the requested. The * recommended port mapping lifetime is 3600 seconds. The * protocol specifies an unsigned integer for this parameter, * however Java will not support that as a data type. Therefore, * the parameter is given as a long. Do not assign values larger * than an unsigned int can handle to this parameter. * @param listener * The {@link MessageResponseInterface} that will respond to the * message result. */ public MapRequestMessage(boolean isTCP, int internalPort, int requestedExternalPort, int requestedPortMappingLifetime, MessageResponseInterface listener) { super(isTCP ? MessageType.MapTCP : MessageType.MapUDP, listener); // Localize. this.internalPort = internalPort; this.requestedExternalPort = requestedExternalPort; this.requestedPortMappingLifetime = requestedPortMappingLifetime; } byte[] getRequestPayload() { byte[] request = new byte[12]; request[2] = 0; // Reserved request[3] = 0; // Reserved shortToByteArray(getInternalPort(), request, 4); // Internal Port shortToByteArray(getRequestedExternalPort(), request, 6); // Requested // External // Port intToByteArray(getRequestedPortMappingLifetime(), request, 8); // Request // Port // Mapping // Lifetime // in // Seconds return request; } void parseResponse(byte[] response) throws NatPmpException { int returnedInternalPort = shortFromByteArray(response, 8); if (returnedInternalPort != internalPort) { throw new NatPmpException("The internal port returned from the gateway was not the same as the one sent."); } internalPort = returnedInternalPort; externalPort = shortFromByteArray(response, 10); portMappingLifetime = intFromByteArray(response, 12); } byte getOpcode() { return getMessageType() == MessageType.MapUDP ? (byte) 1 : (byte) 2; } /** * Gets the internal port on which mapped data will arrive. * * @return The port on this host that is listening. */ public int getInternalPort() { return internalPort; } /** * Get sthe external port that was requested. * * @return The requested external port. */ public int getRequestedExternalPort() { return requestedExternalPort; } /** * Gets the external port that was assigned. * * @return The external port that was assigned. * @throws NatPmpException * Thrown if there was an exception generated during the parsing * of the respnse. */ public Integer getExternalPort() throws NatPmpException { return externalPort; } /** * Gets the requested port mapping lifetime. * * @return The requested port mapping lifetime, in seconds. */ public int getRequestedPortMappingLifetime() { return requestedPortMappingLifetime; } /** * Gets the assigned port mapping lifetime. * * @return The assigned port mapping lifetime, in seconds. * @throws NatPmpException * Thrown if there was an exception generated during the parsing * of the respnse. */ public Integer getPortMappingLifetime() throws NatPmpException { return portMappingLifetime; } }