3 * see AUTHORS for the list of contributors
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 package org.sonews.daemon;
21 import org.sonews.util.Log;
22 import java.io.IOException;
23 import java.net.InetSocketAddress;
24 import java.net.Socket;
25 import java.nio.channels.SocketChannel;
26 import java.util.ArrayList;
27 import java.util.HashMap;
28 import java.util.List;
29 import java.util.ListIterator;
31 import org.sonews.util.Stats;
34 * Daemon thread collecting all NNTPConnection instances. The thread
35 * checks periodically if there are stale/timed out connections and
36 * removes and purges them properly.
37 * @author Christian Lins
40 final class Connections extends AbstractDaemon
43 private static final Connections instance = new Connections();
46 * @return Active Connections instance.
48 public static Connections getInstance()
50 return Connections.instance;
53 private final List<NNTPConnection> connections
54 = new ArrayList<NNTPConnection>();
55 private final Map<SocketChannel, NNTPConnection> connByChannel
56 = new HashMap<SocketChannel, NNTPConnection>();
60 setName("Connections");
64 * Adds the given NNTPConnection to the Connections management.
66 * @see org.sonews.daemon.NNTPConnection
68 public void add(final NNTPConnection conn)
70 synchronized(this.connections)
72 this.connections.add(conn);
73 this.connByChannel.put(conn.getChannel(), conn);
79 * @return NNTPConnection instance that is associated with the given
82 public NNTPConnection get(final SocketChannel channel)
84 synchronized(this.connections)
86 return this.connByChannel.get(channel);
90 int getConnectionCount(String remote)
93 synchronized(this.connections)
95 for(NNTPConnection conn : this.connections)
98 assert conn.getChannel() != null;
100 Socket socket = conn.getChannel().socket();
103 InetSocketAddress sockAddr = (InetSocketAddress)socket.getRemoteSocketAddress();
106 if(sockAddr.getHostName().equals(remote))
111 } // if(socket != null)
118 * Run loops. Checks periodically for timed out connections and purged them
126 int timeoutMillis = 1000 * Config.getInstance().get(Config.TIMEOUT, 180);
128 synchronized (this.connections)
130 final ListIterator<NNTPConnection> iter = this.connections.listIterator();
133 while (iter.hasNext())
136 if((System.currentTimeMillis() - conn.getLastActivity()) > timeoutMillis)
138 // A connection timeout has occurred so purge the connection
141 // Close and remove the channel
142 SocketChannel channel = conn.getChannel();
143 connByChannel.remove(channel);
147 // Close the channel; implicitely cancels all selectionkeys
149 Log.msg("Disconnected: " + channel.socket().getRemoteSocketAddress() +
152 catch(IOException ex)
154 Log.msg("Connections.run(): " + ex, false);
157 // Recycle the used buffers
158 conn.getBuffers().recycleBuffers();
160 Stats.getInstance().clientDisconnect();
167 Thread.sleep(10000); // Sleep ten seconds
169 catch(InterruptedException ex)
171 Log.msg("Connections Thread was interrupted: " + ex.getMessage(), false);