package com.limegroup.gnutella.chat;
import java.io.IOException;
import java.net.Socket;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.ArrayList;
import com.limegroup.gnutella.ActivityCallback;
import com.limegroup.gnutella.ConnectionAcceptor;
import com.limegroup.gnutella.RouterService;
import com.limegroup.gnutella.settings.ChatSettings;
import com.limegroup.gnutella.settings.FilterSettings;
import com.limegroup.gnutella.statistics.HTTPStat;
import com.limegroup.gnutella.util.Comparators;
/**
* This class establishes a connection for a chat, either
* incoming or outgoing, and also maintains a list of all the
* chats currently in progress.
*
* @author rsoule
*/
public final class ChatManager implements ConnectionAcceptor {
/**
* Constant for the <tt>ChatManager</tt> instance, following
* singleton.
*/
private static final ChatManager CHAT_MANAGER = new ChatManager();
/**
* <tt>List</tt> of InstantMessenger objects.
*/
private List _chatsInProgress
= Collections.synchronizedList(new LinkedList());
/**
* Instance accessor for the <tt>ChatManager</tt>.
*/
public static ChatManager instance() {
return CHAT_MANAGER;
}
private ChatManager() {
RouterService.getConnectionDispatcher().
addConnectionAcceptor(this,
new String[]{"CHAT"},
false,
false);
}
/**
* Accepts the given socket for a one-to-one
* chat connection, like an instant messanger.
*/
public void accept(Socket socket) {
Thread.currentThread().setName("IncomingChatThread");
// the Acceptor class recieved a message already,
// and asks the ChatManager to create an InstantMessager
boolean allowChats = ChatSettings.CHAT_ENABLED.getValue();
// see if chatting is turned off
if (! allowChats) {
try {
socket.close();
} catch (IOException e) {
}
return;
}
// do a check to see it the host has been blocked
String host = socket.getInetAddress().getHostAddress();
String[] bannedIPs = FilterSettings.BLACK_LISTED_IP_ADDRESSES.getValue();
List bannedList = Arrays.asList(bannedIPs);
if (bannedList.contains(host) ) {
try {
socket.close();
} catch (IOException e) {
}
return;
}
try {
ActivityCallback callback =
RouterService.getCallback();
InstantMessenger im =
new InstantMessenger(socket, this, callback);
// insert the newly created InstantMessager into the list
_chatsInProgress.add(im);
callback.acceptChat(im);
im.start();
} catch (IOException e) {
try {
socket.close();
} catch (IOException ee) {
}
}
}
/**
* Request a chat connection from the host specified
* returns an uninitialized chat connection. the callback
* will be called when the connection is established or
* the connection has died.
*/
public Chatter request(String host, int port) {
InstantMessenger im = null;
try {
ActivityCallback callback =
RouterService.getCallback();
im = new InstantMessenger(host, port, this, callback);
// insert the newly created InstantMessager into the list
_chatsInProgress.add(im);
im.start();
} catch (IOException e) {
// TODO: shouldn't we do some cleanup here? Remove the session
// from _chatsInProgress??
}
return im;
}
/**
* Remove the instance of chat from the list of chats
* in progress.
*/
public void removeChat(InstantMessenger chat) {
_chatsInProgress.remove(chat);
}
/** blocks incoming connections from a particular ip address */
public void blockHost(String host) {
String[] bannedIPs = FilterSettings.BLACK_LISTED_IP_ADDRESSES.getValue();
Arrays.sort(bannedIPs, Comparators.stringComparator());
synchronized (this) {
if ( Arrays.binarySearch(bannedIPs, host,
Comparators.stringComparator()) < 0 ) {
String[] more_banned = new String[bannedIPs.length+1];
System.arraycopy(bannedIPs, 0, more_banned, 0,
bannedIPs.length);
more_banned[bannedIPs.length] = host;
FilterSettings.BLACK_LISTED_IP_ADDRESSES.setValue(more_banned);
}
}
}
public void unblockHost(String host) {
String[] bannedIPs = FilterSettings.BLACK_LISTED_IP_ADDRESSES.getValue();
List bannedList = Arrays.asList(bannedIPs);
synchronized (this) {
if (bannedList.remove(host) )
FilterSettings.BLACK_LISTED_IP_ADDRESSES.
setValue((String[])bannedList.toArray());
}
}
public void acceptConnection(String word, Socket s) {
HTTPStat.CHAT_REQUESTS.incrementStat();
accept(s);
}
}