View Javadoc

1   /**
2    * This file is part of Waarp Project.
3    * 
4    * Copyright 2009, Frederic Bregier, and individual contributors by the @author tags. See the
5    * COPYRIGHT.txt in the distribution for a full listing of individual contributors.
6    * 
7    * All Waarp Project is free software: you can redistribute it and/or modify it under the terms of
8    * the GNU General Public License as published by the Free Software Foundation, either version 3 of
9    * the License, or (at your option) any later version.
10   * 
11   * Waarp is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
12   * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
13   * Public License for more details.
14   * 
15   * You should have received a copy of the GNU General Public License along with Waarp . If not, see
16   * <http://www.gnu.org/licenses/>.
17   */
18  package org.waarp.ftp.core.session;
19  
20  import java.net.InetAddress;
21  import java.net.InetSocketAddress;
22  import java.util.concurrent.ConcurrentHashMap;
23  
24  import io.netty.channel.Channel;
25  import org.waarp.common.logging.WaarpLogger;
26  import org.waarp.common.logging.WaarpLoggerFactory;
27  import org.waarp.ftp.core.utils.FtpChannelUtils;
28  
29  /**
30   * Class that allows to retrieve a session when a connection occurs on the Data network based on the {@link InetAddress} of the
31   * remote client and the {@link InetSocketAddress} of the server for
32   * Passive and reverse for Active connections. This is particularly useful for Passive mode
33   * connection since there is no way to pass the session to the connected channel without this
34   * reference.
35   * 
36   * @author Frederic Bregier
37   * 
38   */
39  public class FtpSessionReference {
40      /**
41       * Internal Logger
42       */
43      private static final WaarpLogger logger = WaarpLoggerFactory
44              .getLogger(FtpSessionReference.class);
45  
46      /**
47       * Index of FtpSession References
48       * 
49       * @author Frederic Bregier
50       * 
51       */
52      public static class P2PAddress {
53          /**
54           * Remote Inet Address (no port)
55           */
56          public InetAddress ipOnly;
57  
58          /**
59           * Local Inet Socket Address (with port)
60           */
61          public InetSocketAddress fullIp;
62  
63          /**
64           * Constructor from Channel
65           * 
66           * @param channel
67           */
68          public P2PAddress(Channel channel) {
69              ipOnly = FtpChannelUtils.getRemoteInetAddress(channel);
70              fullIp = (InetSocketAddress) channel.localAddress();
71          }
72  
73          /**
74           * Constructor from addresses
75           * 
76           * @param address
77           * @param inetSocketAddress
78           */
79          public P2PAddress(InetAddress address,
80                  InetSocketAddress inetSocketAddress) {
81              ipOnly = address;
82              fullIp = inetSocketAddress;
83          }
84  
85          /**
86           * 
87           * @return True if the P2Paddress is valid
88           */
89          public boolean isValid() {
90              return ipOnly != null && fullIp != null;
91          }
92  
93          @Override
94          public boolean equals(Object arg0) {
95              if (arg0 == null) {
96                  return false;
97              }
98              if (arg0 instanceof P2PAddress) {
99                  P2PAddress p2paddress = (P2PAddress) arg0;
100                 if (p2paddress.isValid() && isValid()) {
101                     return p2paddress.fullIp.equals(fullIp) &&
102                             p2paddress.ipOnly.equals(ipOnly);
103                 }
104             }
105             return false;
106         }
107 
108         @Override
109         public int hashCode() {
110             return fullIp.hashCode() + ipOnly.hashCode();
111         }
112 
113     }
114 
115     /**
116      * Reference of FtpSession from InetSocketAddress
117      */
118     private final ConcurrentHashMap<P2PAddress, FtpSession> hashMap = new ConcurrentHashMap<P2PAddress, FtpSession>();
119 
120     /**
121      * Constructor
122      * 
123      */
124     public FtpSessionReference() {
125     }
126 
127     /**
128      * Add a session from a couple of addresses
129      * 
130      * @param ipOnly
131      * @param fullIp
132      * @param session
133      */
134     public void setNewFtpSession(InetAddress ipOnly, InetSocketAddress fullIp,
135             FtpSession session) {
136         P2PAddress pAddress = new P2PAddress(ipOnly, fullIp);
137         if (!pAddress.isValid()) {
138             logger.error("Couple invalid in setNewFtpSession: " + ipOnly +
139                     " : " + fullIp);
140             return;
141         }
142         hashMap.put(pAddress, session);
143         // logger.debug("Add: {} {}", ipOnly, fullIp);
144     }
145 
146     /**
147      * Return and remove the FtpSession
148      * 
149      * @param channel
150      * @return the FtpSession if it exists associated to this channel
151      */
152     public FtpSession getActiveFtpSession(Channel channel, boolean remove) {
153         // First check Active connection
154         P2PAddress pAddress = new P2PAddress(((InetSocketAddress) channel
155                 .localAddress()).getAddress(), (InetSocketAddress) channel
156                 .remoteAddress());
157         if (!pAddress.isValid()) {
158             logger.error("Couple invalid in getActiveFtpSession: " + channel +
159                     channel.localAddress() + channel.remoteAddress());
160             return null;
161         }
162         // logger.debug("Get: {} {}", pAddress.ipOnly, pAddress.fullIp);
163         if (remove) {
164             return hashMap.remove(pAddress);
165         } else {
166             return hashMap.get(pAddress);
167         }
168     }
169 
170     /**
171      * Return and remove the FtpSession
172      * 
173      * @param channel
174      * @return the FtpSession if it exists associated to this channel
175      */
176     public FtpSession getPassiveFtpSession(Channel channel, boolean remove) {
177         // First check passive connection
178         P2PAddress pAddress = new P2PAddress(channel);
179         if (!pAddress.isValid()) {
180             logger.error("Couple invalid in getPassiveFtpSession: " + channel);
181             return null;
182         }
183         // logger.debug("Get: {} {}", pAddress.ipOnly, pAddress.fullIp);
184         if (remove) {
185             return hashMap.remove(pAddress);
186         } else {
187             return hashMap.get(pAddress);
188         }
189     }
190 
191     /**
192      * Remove the FtpSession from couple of addresses
193      * 
194      * @param ipOnly
195      * @param fullIp
196      */
197     public void delFtpSession(InetAddress ipOnly, InetSocketAddress fullIp) {
198         P2PAddress pAddress = new P2PAddress(ipOnly, fullIp);
199         if (!pAddress.isValid()) {
200             logger.error("Couple invalid in delFtpSession: " + ipOnly + " : " +
201                     fullIp);
202             return;
203         }
204         // logger.debug("Del: {} {}", pAddress.ipOnly, pAddress.fullIp);
205         hashMap.remove(pAddress);
206     }
207 
208     /**
209      * Test if the couple of addresses is already in the hashmap (only for Active)
210      * 
211      * @param ipOnly
212      * @param fullIp
213      * @return True if already presents
214      */
215     public boolean contains(InetAddress ipOnly, InetSocketAddress fullIp) {
216         P2PAddress pAddress = new P2PAddress(ipOnly, fullIp);
217         if (!pAddress.isValid()) {
218             logger.error("Couple invalid in contains: " + ipOnly + " : " +
219                     fullIp);
220             return false;
221         }
222         // logger.debug("Contains: {} {}", pAddress.ipOnly, pAddress.fullIp);
223         return hashMap.containsKey(pAddress);
224     }
225 
226     /**
227      * 
228      * @return the number of active sessions
229      */
230     public int sessionsNumber() {
231         return hashMap.size();
232     }
233 }