View Javadoc

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